c-如果内存未分配给字符串,则出现CS50.h分段故障



在处理CS50问题集(替换(时,我在运行代码时遇到了分段错误。经过一些搜索,我发现将内存(malloc(分配给字符串";输出";修复了该问题。然而,我想了解为什么在这里分配内存是必要的?

如有任何解释,不胜感激。

代码摘录:-请注意,我使用的是cs50.h库

string cipher(string input, string key) {
string output=malloc(strlen(input)+1);
for (int i=0, len = strlen(input); i<len; i++) {
if(isalpha(input[i]) != 0) {
output[i] = substitute(input[i], key);
}
else {
output[i] = input[i];
}
}
return output;
free(output);
}

尽管我对CS50.h字符串了解很多,但我还是知道

string output

只是声明一个名为output的字符指针。因此,在您的代码中实际发生的是,直到您明确声明";strlen(输入(+1";连续内存位置仅属于输出,它们本质上是程序的空闲位置。因此,您的输出指针将只包含第0个索引处的字符。函数返回什么";输出";实际上是一个指针。同时,程序中的某些进程可能会使用输出[0]以外的所有其他内存位置,因为它们从不属于输出字符串。输出仅指向某个字符串的第一个字符。

在C、C++中,绑定检查基本上是由程序员完成的。对于任何任意i,output[i]都不会给出错误,因为它对程序员来说是一个简单的指针运算,即output[i]=*(output+i(。:(

对于初学者,此语句

free(output);

永远不会得到控制,因为它被放在返回语句之后

return output;

而且这也没有道理。是函数的调用方负责释放分配的内存。

您需要动态分配内存,否则,如果您将声明像这样的可变长度数组

char output[strlen(input)+1];

则在退出函数之后,它将不活动,并且试图访问函数外部的数组会导致未定义的行为。

如果你只写

string output;

相当于

char *output;

那么指针输出的值不确定,因为它没有初始化,也没有分配将要复制源字符串的内存。

您可以就地更改源字符串input,而无需再创建一个数组。

在这种情况下,写就足够了

if(isalpha(input[i]) != 0) {
input[i] = substitute(input[i], key);
}

然后你可以放置声明

return input;

请注意,对类型char *使用别名string是个坏主意。

函数声明,如果要像一样重写它

char * cipher(char *input, char *key);

令人困惑。目前尚不清楚字符串输入和键是否在函数中发生了更改。

如果您希望函数从源字符串返回一个新的字符串构建,那么函数声明应该看起来像

char * cipher(const char *input, const char *key);

从而回答您的问题

但是我想了解为什么在这里分配内存是必要的?

如果您想从指针input指向的源字符串创建一个新字符串,那么很明显,您需要分配一个新的字符数组来复制源字符串的元素。

否则,如果要就地更改源字符串,则无需再创建一个数组。

最新更新