我有这样的结构:
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更改为**文本修复了该文本。
答案 0 :(得分:4)
只有NULL
初始化指针或malloc
家庭函数(malloc
,calloc
和realloc
)返回的指针才能传递给另一个{{} 1}}家庭功能。 malloc
初始化时使用字符串文字line->text
,因此"\0"
无法传递给line->text
函数。
另请注意,您无法修改字符串文字。
答案 1 :(得分:2)
其中一个问题是你试图重新分配你自己没有分配的东西。
另一个问题是你试图在AddChar
函数中重新分配一个局部变量,并期望它对调用函数产生任何影响,而不是。
当一个参数传递给一个函数时,它通过值传递 ,这意味着该值被复制到函数中的局部参数变量中,该变量仅在函数内局部变化,并且不会更改更改调用函数时使用的原始变量。你需要的是通过引用传递参数,而C不支持,但你可以使用指针模拟它。在您的情况下,通过使用address-of运算符&
来指向指针。
答案 2 :(得分:0)
据我了解,事实证明strlen无法弄清楚如果text == NULL,则长度应为0 ...
另一方面,section 7.1.4, paragraph 1 C标准声明NULL是strlen
的无效值:
如果函数的参数具有无效值(例如函数域外的值,或程序地址空间外的指针,或空指针,或者当相应参数不是const限定时指向不可修改存储的指针)或者具有可变数量参数的函数不期望的类型(提升之后),行为是未定义的。
虽然我们关注的是无效值,但strcat
会期望它的两个参数都包含字符串。这意味着它们必须包含一个终止于第一个'\0'
字符的字符序列。您已通过在表示第二个参数的数组中添加'\0'
字符来证明这一点,但是您能否证明数组中的'\0'
字符代表您的第一个参数?
*text = (char *) realloc(*text, strlen(*text)+2);
除了空指针,模式x = realloc(x, ...);
的任何内容都是错误的。有关详细信息,请参阅Proper usage of realloc
。
*text= (char *) realloc(*text, sizeof(*text)+2);
至于此,它起初似乎对你有用,但我可以向你保证它已经坏了。重要的是要意识到您打算分配字符而不是char *
s,因此sizeof(*text)
(sizeof (char *)
}在此处无效。
通常这会分配6到10个字符。如果溢出该缓冲区,则行为未定义。那是什么意思?嗯,定义未定义的行为是一个悖论,但未定义行为的典型后果包括"什么都没有"并且"它工作正常"对于某些系统来说,"段错误"和#34; heartbleed"对于其他系统;尽管如此,它仍然不便携。
我也遇到了问题
void AddChar(char *text, char c) { text = "something"; }
不更改line->文本,但将* text更改为**文本修复了该文本。
我很好奇你认为AddChar(NULL, 42);
会做什么,当AddChar
被定义为这样的时候......你认为它会分配空指针常量吗? NULL
到"something"
的字符串文字?
C不支持传递引用。传递参数时(例如,指针,例如隐式转换为指针的数组表达式),幕后发生的事情是声明新变量(在本例中为参数{ {1}}是一个变量)并且该值的副本(在本例中为指针)被分配给该变量。这被称为"按值传递"。
当您传递指针并修改指针指向的东西时(例如,使用char *text
或*pointer = ...
),您将模拟传递引用;您正在修改变量引用的对象,而不是修改变量本身。
哦,还有一件事,尽管链接到"正确使用pointer[x] = ...
",you should not cast the return value of malloc
(or `realloc) in C。
答案 3 :(得分:0)
不同意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';
}