【问题标题】:Segmentation fault - char pointer分段错误 - 字符指针
【发布时间】:2009-06-03 06:18:27
【问题描述】:

在下面的代码中,行:

*end = *front;

给出分段错误。我问了一个类似的问题here,但我不确定这是否是因为我有两个 num 副本。请解释为什么它是段错误。谢谢。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char* getPalin(char* num);

int main()
{
    char* num = (char*)malloc(100);

    num = "123456";

    printf("%s\n", getPalin(num) );

    return 0;
}

char* getPalin(char* num)
{
    int length = strlen(num);

    if ( length % 2 == 0 )
    {
        char* front = num;
        char* end = num + strlen(num) - 1;  //pointer to end

        while( front != num + (length/2) )  //pointers not middle yet
        {
            *end = *front;

            printf("%c", *end);

            front++;
            end--;
        }
    }

    return num;
}

【问题讨论】:

    标签: c segmentation-fault


    【解决方案1】:

    这两行:

    char* num = (char*)malloc(100);
    num = "123456";
    

    有以下效果。

    第一个分配 100 个字节并将num 设置为指向这些字节。

    第二个更改 num 指向字符串“123456”,几乎可以肯定它在只读内存中。

    任何更改只读内存内容的尝试都将导致分段违规。在尝试更改之前,您需要将字符串复制到 malloc'd num 中:

    strcpy (num, "123456");
    

    这就是你当前应该拥有的那一行:

    num = "123456";
    

    【讨论】:

      【解决方案2】:

      使用

      strncpy(num, "123456", 100);
      

      而不是

      num = "123456";
      

      【讨论】:

      • 对不起,不是sizeof(num),而是分配内存的大小,即100。即strncpy(num, "123456", 100);
      • OP 要求解释,但您只提供了一个解决方案。并且永远不要忘记在 strncpy 之后手动添加空终止符,因为不能保证 strncpy 添加它。我知道这在本例中不相关,因为“123456”小于 100 个字节,但如果您决定使用 strncpy 而不是 strcpy,请正确使用它 - 您避免了一个潜在问题(缓冲区溢出)但引入了另一个问题(未终止的字符串) .
      • @qrdl - 只要 strncpy 中指定的目标大小大于字符串长度,strncpy 就会自动填充空字符。只有当目标大小被指定为小于要复制的字符串长度时,才会丢失空终止符。另一个要点是记住 strncpy 不会检查目标内存中是否有足够的空间。所以我想 strncpy(num,"123456", sizeof(num)) 会更正确。
      • num 是一个“char*”,所以 sizeof(num) 将为 4(如果你的硬件比我好,则为 8)。
      • @ChrisBD - 仔细阅读我的评论。我写道,我知道在这种情况下这并不重要。仅供参考 - sizeof(num) 在这种情况下是 sizeof(char ) 因为 num 在参数列表中被声明为 char
      【解决方案3】:

      根据康斯坦丁的回答。

      您已经使用 malloc 语句为 num 分配了内存。

      如果你没有,那么你可以逃脱:

      char* num = "123456";
      

      它将动态定义和分配内存,但它很可能被分配为常量,因此是只读的。

      使用 strncpy 而不是 strcpy 复制“123456”将确保字符串空终止符末尾之外的任何额外空间也初始化为空,只要您将 n 指定为 100(对于您的示例)。否则,如果不将 malloc 分配的内存初始化为 null (memset(num, 0, 100)),那么可以想象你可以跨过字符串的末尾。

      哦,差点忘了。建议使用 strcpy_s 或 strncpy_s,因为它们更安全,尽管对于您的代码来说这无关紧要。

      【讨论】:

      • 我实际上认为这两个 _s() 函数对于不知道如何进行防御性编码的人来说是一个拐杖 [即,首先检查先决条件 - 我什至从未发现需要使用 strncpy () 并且我的代码仍然与使用 _s() 变体的任何代码一样“安全”]。最重要的是,它们还不是标准的一部分。
      • 因此我说可取的原因。令我惊讶的是,有多少商业软件让自己对缓冲区溢出攻击保持开放。
      【解决方案4】:

      错误原因是:

        char* num = (char*)malloc(100);
      

      在这一行中,您将 num 声明为指向数组的指针或指向其第一个元素的指针,而不是字符串。

       num = "123456";
      

      这一行你使用了 num ,因为你将它声明为一个字符串。这是违反分段的,因此是分段错误。您的代码的首选(正确)语法是:

         char num[100];
         strcpy(num,"123456"); //Even if you use num="123456"; here it would still be wrong
      

        char* num = (char*)malloc(100);
        strcpy(num,"123456");
      

        char num[100]={'1','2','3','4','5','6'};
      

      这些都可以完成你的工作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-07-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多