繁体   English   中英

为什么我不能重新分配此字符串?

[英]Why can't I realloc this string?

我有一个这样的结构:

typedef struct TEXT {
    char *text;
    struct TEXT *next;
} TEXT;

在某些函数中,我有类似以下内容:

TEXT *line = (TEXT *) malloc(sizeof(TEXT));
line->text = NULL; // was "\0" before
char current = getchar();
while (current != '\n') {
    AddChar(&(line->text), current); // Was AddChar(line->text, current);
    current = getchar();
}

而AddChar函数是这样的:

void AddChar(char **text, char c) { //was char *text
    *text = (char *) realloc(*text, strlen(*text)+2); //was text = ...
    char char_array[2] = {c, '\0'); 
    strcat(*text, char_array); //was strcat(text, char_array);
}

不幸的是,程序崩溃了。

据我了解,结果strlen不能弄清楚如果text == NULL,则长度应为0 ...

无论如何,使用此AddChar函数,一切正常:

void AddChar(char **text, char c) {
    if (*text == NULL) {
        *text = (char *) malloc(2);
        (*text)[0] = c;
        (*text)[1] = '\0';
    }
    else {
        *text= (char *) realloc(*text, sizeof(*text)+2);
        char char_array[2] = { c , '\0' };
        strcat(*text, char_array);
    }
}

我也有一个问题

void AddChar(char *text, char c) {
    text = "something";
}

不更改line-> text,而是将* text更改为** text即可解决此问题。

只能将NULL初始化指针或malloc系列函数( malloccallocrealloc )返回的指针传递给另一个malloc家族函数。 line->text用字符串文字"\\0"初始化,因此line->text无法传递给realloc函数。
还要注意,您不能修改字符串文字。

问题之一是您尝试重新分配自己没有分配的东西。

另一个问题是,您尝试在AddChar函数中重新分配一个局部变量,并希望它对调用函数有任何影响,但不会。

将参数传递给函数时,它会通过传递这意味着将值复制到函数中的局部参数变量中,该变量仅在函数内部局部存在,并且更改该值不会更改调用该函数时使用的原始变量。 您需要通过C不支持的引用传递参数,但是您可以使用指针进行模拟 在您的情况下,可以使用地址运算符&指向该指针。

据我了解,结果strlen不能弄清楚如果text == NULL,则长度应为0 ...

另一方面,C标准第7.1.4节第1段指出NULL是strlen的无效值:

如果函数的参数具有无效的值(例如,函数域之外的值,或者程序地址空间之外的指针,或者为空指针 ,或者指向相应参数时指向不可修改存储的指针) (具有const限定符)或参数数量可变的函数所不希望的类型(升级后),则行为未定义。


当我们讨论无效值的问题时strcat会期望两个参数都包含字符串。 这意味着它们必须都包含一个以第一个'\\0'字符结尾的字符序列。 您已经通过在代表第二个参数的数组中添加一个'\\0'字符来证明了这一点,但是可以证明在代表您的第一个参数的数组中存在一个'\\0'字符吗?


 *text = (char *) realloc(*text, strlen(*text)+2); 

除了空指针,任何模式x = realloc(x, ...); 是错的。 有关更多信息,请参见realloc正确用法


 *text= (char *) realloc(*text, sizeof(*text)+2); 

对此,它乍看起来似乎对您有用,但是我可以向您保证它已损坏。 重要的是要意识到您打算分配字符,而不是char * s,因此sizeof(*text) (即sizeof (char *) )在这里无效。

通常,这将分配6到10个字符。 如果您溢出该缓冲区,则行为是不确定的。 这意味着什么? 嗯,定义未定义的行为将是一个悖论,但是未定义行为的典型后果包括:对于某些系统,“什么都没有”和“工作得很好”,而对于其他系统,则是“段错误”和“令人沮丧”。 但是它不是便携式的。


我也有一个问题

 void AddChar(char *text, char c) { text = "something"; } 

不更改line-> text,而是将* text更改为** text即可解决此问题。

我对您的想法感到好奇, AddChar(NULL, 42); 会这样,当AddChar定义时...您认为它会将空指针常量NULL分配给字符串"something"吗?

C不支持传递引用。 当您传递参数(例如,指针,例如隐式转换为指针的数组表达式)时,在幕后发生的事情是声明了一个新变量 (在这种情况下,参数char *text是变量),并且该值的副本(在本例中为指针)被分配给该变量。 这就是所谓的“按值传递”。

当您传递一个指针,并修改该指针所指向的对象时(例如,通过使用*pointer = ...pointer[x] = ... ),您就在模拟传递引用。 您正在修改变量引用的对象,而不是修改变量本身。


哦,还有一件事,尽管链接到“正确使用realloc ”,但您不应在C中强制转换malloc (或`realloc)的返回值

不赞成OP的最终“无论如何,使用此AddChar函数,一切正常:”,因为这样不会分配足够的内存。

建议

void AddChar(char **text, char c) {
    size_t length = strlen(*text); 
    *text = realloc(*text, length + 2);  // proper size calculation
    if (*text == NULL) {  // check if successful
      abort(-1);
    } 
    (*text)[length] = c;
    (*text)[length + 1] = '\0';
}

暂无
暂无

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

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