简体   繁体   English

动态内存分配+截断字符串问题

[英]Dynamic memory allocation + truncating a string issue

I've been fooling around with malloc, realloc and free in order to write some basic functions to operate on C strings (char*). 我一直在鬼混malloc,realloc和free,以便编写一些基本函数来对C字符串(char *)进行操作。 I've encountered this weird issue when erasing the last character from a string. 从字符串中删除最后一个字符时,我遇到了这个奇怪的问题。 I wrote a function with such a prototype: 我用这样的原型编写了一个函数:

int string_erase_end (char ** dst, size_t size);

It's supposed to shorten the "dst" string by one character. 应该将“ dst”字符串缩短一个字符。 So far I have come up with this code: 到目前为止,我已经提出了以下代码:

int string_erase_end (char ** dst, size_t size)
{
    size_t s = strlen(*dst) - size;
    char * tmp = NULL;
    if (s < 0) return (-1);
    if (size == 0) return 0;
    tmp = (char*)malloc(s);
    if (tmp == NULL) return (-1);
    strncpy(tmp,*dst,s);
    free(*dst);
    *dst = (char*)malloc(s+1);
    if (*dst == NULL) return (-1);
    strncpy(*dst,tmp,s);
    *dst[s] = '\0';
    free(tmp);
    return 0;
}

In main(), when I truncate strings (yes, I called malloc on them previously), I get strange results. 在main()中,当我截断字符串时(是的,我之前在它们上调用了malloc),我得到了奇怪的结果。 Depending on the number of characters I want to truncate, it either works OK, truncates a wrong number of characters or throws a segmentation fault. 根据我要截断的字符数,它可以正常工作,截断错误的字符数或引发分段错误。

I have no experience with dynamic memory allocation and have always used C++ and its std::string to do all such dirty work, but this time I need to make this work in C. I'd appreciate if someone helped me locate and correct my mistake(s) here. 我没有动态内存分配的经验,并且一直使用C ++及其std :: string来完成所有此类肮脏的工作,但是这次我需要在C中进行这项工作。如果有人帮助我找到并纠正了我的问题,我将不胜感激。这里的错误。 Thanks in advance. 提前致谢。

According to your description your function is supposed to erase the last n characters in a string: 根据您的描述,您的函数应该擦除字符串中的最后n个字符:

/* Assumes passed string is zero terminated... */
void string_erase_last_char(char * src, int num_chars_to_erase)
{
    size_t len = strlen(src);

    if (num_chars_to_erase > len)
    {
        num_chars_to_erase = len;
    }

    src[len - num_chars_to_erase] = '\0';
} 

The first strncpy() doesn't put a '\\0' at the end of tmp. 第一个strncpy()不会在tmp的末尾添加“ \\ 0”。

Also, you could avoid a double copy: *dst = tmp; 同样,您可以避免重复副本:* dst = tmp;

I don't understand the purpose of the size parameter. 我不明白size参数的用途。

If your strings are initially allocated using malloc() , you should just use realloc() to change their size. 如果最初使用malloc()分配了字符串,则应仅使用realloc()更改其大小。 That will retain the content automatically, and require fewer operations: 这将自动保留内容,并且需要较少的操作:

int string_erase_end (char ** dst)
{
  size_t len;
  char *ns;

  if (dst == NULL || *dst == NULL)
   return -1;

  len = strlen(*dst);
  if (len == 0)
    return -1;

  ns = realloc(*dst, len - 1);
  if (ns == NULL)
   return -1;
  ns[len - 1] = '\0';
  *dst = ns;

  return 0;
}

In the "real world", you would generally not change the allocated size for a 1-char truncation; 在“现实世界”中,通常不会更改1个字符的截断的分配大小; it's too inefficient. 它太低效了。 You would instead keep track of the string's length and its allocated size separately. 相反,您应该分别跟踪字符串的长度和分配的大小。 That makes it easy for strings to grow; 这使得字符串很容易增长。 as long as there is allocated space already, it's very fast to append a character. 只要已经分配了空间,追加字符就非常快。

Also, in C you never need to cast the return value of malloc() ; 同样,在C语言中,您无需malloc()的返回值; it serves no purpose and can hide bugs so don't do it. 它没有任何用途,并且可以隐藏错误,所以不要这样做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM