C语言中strlen的未处理异常

时间:2012-05-09 16:35:19

标签: c strlen

我一直被困在这个上,我不是C的专家。基本上,我正在尝试制作一个“安全地”将角色划分到现有角色*的功能。

我试图从这个例子中获得“动态分配”方法:

Using strcat in C

我做了一些修改,我删除了由realloc函数设置的var(编译器说它返回了void)。我还修改它只附加一个字符而不是一个字符数组。我认为这会改变“realloc”参数,所以不是传递加法字符串的长度,而是传入“sizeof(char)”(x2,因为原来有一个额外的sizeof char,我想是因为null终止符?)

char *buffer = NULL;

int mystrcat(char addition)
{
   realloc(buffer, strlen(buffer) + sizeof(char)*2);
   if (!buffer)
     return 0;
   strcat(buffer, addition);
   return 1;
}

我称之为:

if(!safestrcat(str[i+j]))
    printf("Out of Memory");

出于某种原因,我看到了这一点:

  

myProg.exe中0x60f0d540(msvcr100d.dll)的未处理异常:   0xC0000005:访问冲突读取位置0x00000000。

调试器在第81行显示strlen.asm:

main_loop:
    mov     eax,dword ptr [ecx]     ; read 4 bytes

如果这是一个新问题,我很抱歉,但是发生了什么?为什么添加char没有附加到缓冲区?

抱歉,我应该补充说,它成功编译。

5 个答案:

答案 0 :(得分:6)

  • 你忘记了一个论点
  • 根据定义,
  • sizeof(char)为1
  • 您的realloc代码已损坏
  • strcat不会将char作为其第二个参数
  • 我只是返回新创建的字符串,例如strcat
char* mystrcat(char* buffer, char addition) {
    unsigned oldlen = strlen(buffer);
    buffer = realloc(buffer, oldlen + 2);
    if (buffer == NULL)
        return NULL;

    buffer[oldlen + 0] = addition;
    buffer[oldlen + 1] = '\0';
    return buffer;
}

然而,请注意两件事:

  1. 必须使用有效的初始化指针调用mystrcat - 与strcat相同!
  2. 如果失败,函数返回NULL - 在这种情况下,调用者有责任确保释放原始缓冲区的内存。这意味着您不能将该函数称为

    buffer = mystrcat(buffer, 'x');
    

    - 这可能会导致内存泄漏。

  3. 所以正确的用法是:

    char* something = "hello";
    char* buffer = malloc(sizeof(something) + 1);
    strcpy(buffer, something);
    
    char* new_buffer = mystrcat(buffer, 'x');
    if (new_buffer == NULL) {
        free(buffer);
        exit(1);
    }
    
    buffer = new_buffer;
    

    是的,令人费解。这是安全记忆操作的代价。

答案 1 :(得分:2)

您对realloc的调用完全被破坏 - 您需要检查是否成功,然后将函数的结果重新分配给现有指针。

您还需要char *作为第二个参数传递给strcat,而不是char

变化:

int mystrcat(char addition)
{
   realloc(buffer, strlen(buffer) + sizeof(char)*2);
   if (!buffer)
     return 0;
   strcat(buffer, addition);
   return 1;
}

为:

int mystrcat(char addition)
{
   char st[2] = { addition, '\0' };               // make temporary string to hold `addition`
   int len = buffer != NULL ? strlen(buffer) : 0; // NB: handle case where `buffer` has not yet been allocated
   char * tmp = realloc(buffer, len + 2);         // increase size of `buffer`
   if (!tmp)                                      // handle realloc failure
     return 0;
   buffer = tmp;
   strcat(buffer, st);                            // append `addition`
   return 1;
}

答案 2 :(得分:2)

其他答案中给出了很多非常好的建议,但是您获得访问冲突的原因是因为bufferNULL开头。然后你做strlen(buffer)strlen()通过计算从传入的地址开始直到达到'\0'的字符为止。所以在你的情况下,第一次,你取消引用空指针。

答案 3 :(得分:1)

char * mystrcat(char *str, char addition)
{
   size_t len;
   len = strlen(str);
   str = realloc(str, len + 2);
   if (!str)
     return NULL; /* ... */
   str[len++] = addition;
   str[len] = 0;
   return str;
}

答案 4 :(得分:0)

char *mystrcat(char *buffer, char addition) {
    char *bb;
    size_t ll;
    ll = buffer ? strlen(buffer) : 0;
    bb = realloc(buffer, ll + 2);
    if(!bb){
      fprintf(stderr, "Memory exhausted in function: mystrcat !\n");
      exit(EXIT_FAILURE);
    }
    buffer = bb; // Safe!!!
    buffer[ll] = addition;
    buffer[ll+1] = '\0';
    return buffer;
}

这样的事情。因此,如果没有记忆,那么在完成申请之前,您根本无法做任何事情。如果只是你的系统没有关闭。

这是一个严重的错误!但你可以看到这条消息。在日志中肯定。如果传递错误的prt缓冲区,则无法保证正常工作。例如,如果您忘记设置null终止符。 strlen发生错误!