1

我已经在这个问题上停留了一段时间,我不是 C 方面的专家。基本上,我正在尝试制作一个函数,可以“安全地”将字符转换为现有的 char *。

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

在 C 中使用 strcat

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

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

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

对不起,我应该补充一点,它编译成功。

4

5 回答 5

6
  • 你忘记了一个论点
  • sizeof(char)根据定义为 1
  • 你的realloc代码坏了
  • strcat不以 achar作为第二个参数
  • 我只是返回新创建的字符串,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');
    

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

所以正确的用法是:

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;

是的,令人费解。这是安全内存操作的代价。

于 2012-05-09T16:40:48.197 回答
2

其他答案中已经给出了大量非常好的建议,但是您收到访问冲突的原因是buffer因为NULL. 然后你做strlen(buffer)strlen()工作原理是从传入的地址开始计数字符,直到到达'\0'. 因此,在您的情况下,您第一次取消引用空指针。

于 2012-05-09T17:08:56.010 回答
2

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

您还需要将 achar *作为第二个参数传递给strcat,而不是 a 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;
}
于 2012-05-09T16:38:27.027 回答
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;
}
于 2012-05-09T16:44:20.880 回答
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 缓冲区,则无法保证正常工作。例如,如果您忘记设置空终止符。strlen 发生错误!

于 2014-06-05T05:37:35.430 回答