2010-07-01 36 views
5

我有一个头文件中定义一个结构如下:为什么在全局或外部声明结构时会出现段错误?

#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都是正确和有意义的。

+5

这看起来像C,而不是C++? – 2010-07-01 13:59:32

+1

变量名称看起来像一只猫正在穿过键盘。 – 2010-07-01 14:19:29

+2

这是一只匈牙利猫,因为我确定Freakzoid的猫也是。 – maxwellb 2010-07-01 14:24:13

回答

3

你的连接可以简单地扔掉符号,它认为不使用(GNU链接这样做) 。在这种情况下,您可以显式链接目标文件和该符号。

使用C++,您无法控制在其他编译单元中定义的全局对象的初始化顺序(请参阅http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.12)。

使用“首次使用时的构造”成语,它仅仅意味着将静态对象包裹在函数中。

+0

非常感谢!这解决了它。 – relet 2010-07-02 08:25:34

2

如果您有:

// structs.hpp 
#define LC_ERR_LEN 300 
typedef struct dLC_ERRMSG { 
    short nr; 
    short strategy; 
    char tx[LC_ERR_LEN]; 
} LC_ERRMSG; 

和:

// main.cpp 
#include "structs.hpp" 
LC_ERRMSG err; 

int main() 
{ 
    // ... 

    char *szError; 
    szError = strerror(sStatus); 
    snprintf(err.tx, LC_ERR_LEN, "%s - %s", szFilename, szError); 
} 

那么这应该工作。但是,如果您切换的main.cpp下联:

extern LC_ERRMSG err; 

,那么你需要确保为err存储被编译成目标文件之一。例如,你可以编译这个源:

// globals.cpp 
#include "structs.hpp" 

LC_ERRMSG err; 

所得globals.o链接到main.o

任何一种方法都不应引起分段错误。如果您遇到分段错误,那么编译globals.cpp时,编译main.cpp时,问题可能是LC_ERR_LEN有不同的值。或者,也许szFilenameszErrorNULL /坏。 printf系列无法打印NULL或格式标记为%s的错误指针;下面的代码会导致分段错误:

#include <stdio.h> 

int main() 
{ 
    printf("%s\n", NULL); 
} 

编辑:我认为问题的另一个潜在原因。如果您使用的是C编译器,则可能会出现符号冲突,因为err是一个符号,可用作大型项目中几个不同全局变量的名称。如果您使用的是C++编译器,那么名称修改过程应确保每个err都有自己的符号。只要确保你正在编译为C++。

+0

感谢您的回答和麦克斯韦尔伯的答复。在我试图通过在其他地方声明“err”来缩小问题之前,发布的workforme maxwellb与我最初的代码相似。我也正在用g ++编译为C++。到目前为止没有运气。 困扰我的是我不知道err.tx如何被破坏,即使在此期间还有其他代码正在使用它。它没有被动态分配,所以我可以意外释放它。 – relet 2010-07-01 15:12:42

+0

使用你的调试器,你会验证szFilename和szError在snprintf行不是''NULL','szFilename'是正确的空终止?另外,什么是地址'err.tx'? – 2010-07-01 16:20:03

2

丹尼尔答案+1。这是一个适合我的作品。适合你吗? Upvote丹尼尔的答案。


// structs.hpp 
#define LC_ERR_LEN 300 
typedef struct dLC_ERRMSG { 
    short nr; 
    short strategy; 
    char tx[LC_ERR_LEN]; 
} LC_ERRMSG; 

// error.cpp 
#include "structs.hpp" 

LC_ERRMSG err; 

// main.cpp 
#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include "structs.hpp" 
extern LC_ERRMSG err; 

int main() 
{ 
    // ... 
    char *szFilename = "EXAMPLE.LOG"; 
    int sStatus = 0; 
    char *szError; 
    szError = strerror(sStatus); 
    snprintf(err.tx, LC_ERR_LEN, "%s - %s", szFilename, szError); 

    printf("err.tx: %s", err.tx); 
} 

// Output: 
err.tx: EXAMPLE.LOG - No error 
相关问题