为什么在全局或外部声明结构时会出现段错误?
我在标头中定义了一个结构,如下所示:
#define LC_ERR_LEN 300
typedef struct dLC_ERRMSG {
short nr;
short strategy;
char tx[LC_ERR_LEN];
} LC_ERRMSG;
我在代码中使用它:
LC_ERRMSG err;
char *szError;
szError = strerror(sStatus);
snprintf(err.tx,LC_ERR_LEN," %s - %s",szFilename,szError);
/* do something with our error string */
这有效。但是,如果我全局声明 LC_ERRMSG err; ,即在它所使用的函数之外,甚至是 extern LC_ERRMSG err; (这是我的初衷,因为我想能够在中央位置读出错误状态),代码在 snprintf 调用时出现段错误。
你能给我任何线索吗?
ddd 告诉我,当全局声明时,内存被初始化为全零,或者至少在声明为 extern 时初始化并可读。值 szFilename、szError 和 LC_ERR_LEN 都是正确且有意义的。
I have a struct defined in a header as follows:
#define LC_ERR_LEN 300
typedef struct dLC_ERRMSG {
short nr;
short strategy;
char tx[LC_ERR_LEN];
} LC_ERRMSG;
Which I use in my code as such:
LC_ERRMSG err;
char *szError;
szError = strerror(sStatus);
snprintf(err.tx,LC_ERR_LEN," %s - %s",szFilename,szError);
/* do something with our error string */
That works. If however, I declare LC_ERRMSG err;
globally - i.e. outside the function it is used, or even extern LC_ERRMSG err;
(which was my original intention, as I would want to be able to read out the error status in a central location), the code segfaults at the snprintf call.
Can you give me any clues why?
ddd tells me that the memory is initialized to either all zeroes when declared globally, or at least initialized and readable when declared extern. The values szFilename, szError and LC_ERR_LEN are all correct and meaningful.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
你的链接器可以简单地丢弃它认为没有使用的符号(GNU 链接器就是这样做的)。在这种情况下,您可以将目标文件与该符号显式链接。
使用 C++,您无法控制在其他编译单元中定义的全局对象的初始化顺序,无需任何额外的努力(请参阅 http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.12)。
使用“首次使用时构造”习惯用法,这只是意味着将静态对象包装在函数内。
Your linker can simply throw away the symbols, which it believes are not used (the GNU linker does so). In this case you can explicitly link the object file with that symbol.
With C++ you can not control the order of initialization of global objects defined in other compilation units without any additional efforts (see http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.12).
Use the "construct on first use" idiom, which simply means to wrap your static object inside a function.
如果你有:
和:
那么这应该有效。但是,如果您将
main.cpp
的第二行切换为:那么您需要确保
err
的存储被编译到您的目标文件之一中。例如,您可以编译此源:并将生成的
globals.o
链接到main.o
。任何一种方法都不应导致分段错误。如果您遇到分段错误,则问题可能是编译
globals.cpp
时LC_ERR_LEN
的值与编译main.cpp
时的值不同。 code> 正在编译。或者,szFilename
或szError
可能是NULL
/bad。printf
系列无法打印NULL
或带有格式标志%s
的错误指针;以下代码会导致分段错误:编辑:我想到了问题的另一个潜在原因。如果您使用 C 编译器,则可能会发生符号冲突,因为
err
是一个可以用作大型项目中多个不同全局变量的名称的符号。如果您使用的是 C++ 编译器,则名称修改过程应确保每个err
都有自己的符号。只要确保您正在编译为 C++ 即可。If you have:
and:
then this should work. However, if you switch the second line of
main.cpp
to:then you need to make sure that the storage for
err
is compiled into one of your object files. For example, you could compile this source:and link the resulting
globals.o
intomain.o
.Either of the approaches should not cause a segmentation fault. If you are getting a segmentation fault, then the problem could be that
LC_ERR_LEN
has a different value whenglobals.cpp
is being compiled than whenmain.cpp
is being compiled. Or, perhapsszFilename
orszError
areNULL
/bad. Theprintf
family cannot printNULL
or bad pointers with format flag%s
; the following code causes a segmentation fault:EDIT: I thought of another potential cause of the problem. You could have a symbol clash if you are using a C compiler as
err
is a symbol that could be in use as the name of several, different global variables in a large project. If you are using a C++ compiler, then the name mangling process should ensure that eacherr
has its own symbol. Just make sure that you are compiling as C++.丹尼尔的回答+1。这是一个为我工作的作品。对你有用吗?支持丹尼尔的回答。
+1 for Daniel's Answer. Here's a Works-for-me. Works for you? Upvote Daniel's answer.