我在使用strncpy和(指向结构) - >(成员)表示法时遇到分段错误:
我简化了我的代码.我初始化一个结构并将其所有标记设置为空字符串.然后声明一个指向结构的指针,并为其分配结构的地址.
我将指针传递给一个函数.我可以在函数的开头打印出结构的内容,但如果我尝试在strncpy函数中使用tp - > mnemonic,我会得到seg错误.谁能告诉我我做错了什么?
typedef struct tok {
char* label;
char* mnem;
char* operand;
}Tokens;
Tokens* tokenise(Tokens* tp, char* line) {
// This prints "load"
printf("Print this - %s\n", tp -> mnem);
// This function gives me segmentation fault
strncpy(tp -> mnem, line, 4);
return tp;
}
int main() {
char* line = "This is a line";
Tokens tokens;
tokens.label = "";
tokens.mnem = "load";
tokens.operand = "";
Tokens* tp = &tokens;
tp = tokenise(tp, line);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我已经使用printf语句来确认代码肯定在strncpy函数处停止执行.
问题是tp-> mnem指向一个字符串文字,通常在只读的内存段中分配.因此覆盖它是违法的.很可能你需要做的是这样的事情:
Tokens tokens;
tokens.label = "";
tokens.mnem = strdup("load");
tokens.operand = "";
Run Code Online (Sandbox Code Playgroud)
这将为您提供动态分配的内存块,然后您可以根据需要随意写入.当然,你还有其他一些问题:首先,你需要记住以后再释放那个记忆free; 第二,你必须知道你分配的缓冲区的大小,这样你就不会覆盖它.
如果您知道内容mnem永远不会超过4个字节,那么您可能会改变您的结构声明,如下所示:
typedef struct tok {
char* label;
char mnem[5]; // note: +1 byte for a NULL terminator
char* operand;
}Tokens;
Run Code Online (Sandbox Code Playgroud)
然后,你会像这样初始化它:
Tokens tokens;
tokens.label = "";
strcpy(tokens.mnem, "load");
tokens.operand = "";
Run Code Online (Sandbox Code Playgroud)
mnem虽然您仍有一些超出缓冲区的风险,但这可以减轻您管理内存的责任.
以下行
tokens.mnem = "load"
Run Code Online (Sandbox Code Playgroud)
分配mnem给字符串文字的地址,字符串文字通常位于只读数据段中,因此使用strncpy()或任何其他功能更改此内存将失败.