为什么在全局或外部声明结构时会出现段错误?

时间:2010-07-01 13:35:39

标签: c++ struct extern segmentation-fault printf

我在标题中定义了一个结构,如下所示:

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

3 个答案:

答案 0 :(得分:3)

您的链接器可以简单地丢弃它认为未使用的符号(GNU链接器会这样做)。在这种情况下,您可以显式链接目标文件与该符号。

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

使用“首次使用时构造”这个习惯用法,它只是意味着将静态对象包装在一个函数中。

答案 1 :(得分: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

这两种方法都不应该导致分段错误。如果您遇到分段错误,那么问题可能是LC_ERR_LEN在编译globals.cpp时的值与编译main.cpp时的值不同。或者,szFilenameszError可能是NULL /坏。 printf系列无法使用格式标记NULL打印%s或不良指针;以下代码导致分段错误:

#include <stdio.h>

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

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

答案 2 :(得分:2)

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


// 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