【问题标题】:Segmentation Fault: C-Program migrating from HPUX to Linux分段错误:C 程序从 HPUX 迁移到 Linux
【发布时间】:2017-02-24 13:08:05
【问题描述】:

我正在尝试将一个小型 c 程序从 hpux 迁移到 linux。该项目编译良好,但在运行时崩溃,向我显示分段错误。我已经尝试使用 strace 和 gdb 查看镜子后面的内容,但仍然不明白。相关(截断)部分:

tts_send_2.c

包含一个方法

int sequenznummernabgleich(int sockfd, char *snd_id, char *rec_id, int timeout_quit) {
  TS_TEL_TAB tel_tab_S01;
  int n;

  # truncated
}

从该文件中调用,如下所示:

. . .
. . .  
switch(sequenznummernabgleich(sockfd,c_snd_id,c_rec_id,c_timeout_quit)) {

         /* kritischer Fehler */
         case -1:
. . .
. . .

在调用该方法时,我遇到了分段错误(gdb 输出):

Program received signal SIGSEGV, Segmentation fault.
0x0000000000403226 in sequenznummernabgleich (sockfd=<error reading variable: Cannot access memory at address 0x7fffff62f94c>, 
    snd_id=<error reading variable: Cannot access memory at address 0x7fffff62f940>, rec_id=<error reading variable: Cannot access memory at address 0x7fffff62f938>, 
    timeout_quit=<error reading variable: Cannot access memory at address 0x7fffff62f934>) at tts_snd_2.c:498
498 int sequenznummernabgleich(int sockfd, char *snd_id, char *rec_id, int timeout_quit) {

我就是不明白。当我进入使用 gdb 调用该方法的行时,所有变量看起来都很好:

1008    switch(sequenznummernabgleich(sockfd,c_snd_id,c_rec_id,c_timeout_quit)) {
    (gdb) p sockfd
    $9 = 8
    (gdb) p &sockfd
    $10 = (int *) 0x611024 <sockfd>
    (gdb) p c_snd_id
    $11 = "KR", '\000' <repeats 253 times>
    (gdb) p &c_snd_id
    $12 = (char (*)[256]) 0xfde220 <c_snd_id>
    (gdb) p c_rec_id
    $13 = "CO", '\000' <repeats 253 times>
    (gdb) p &c_rec_id
    $14 = (char (*)[256]) 0xfde560 <c_rec_id>
    (gdb) p c_timeout_quit
    $15 = 20
    (gdb) p &c_timeout_quit
    $16 = (int *) 0xfde660 <c_timeout_quit>

我还创建了一个 strace 输出。这是关于上面显示的代码的最后一部分:

strace output

有什么想法吗?我已经在网上搜索了几个小时,当然也搜索了 stackoverflow,但没有找到一个非常相似的案例。

谢谢

克里兹

【问题讨论】:

  • 崩溃在哪一行?您可以在调用函数之前发布代码(即变量声明和在调用时将它们设置为它们的值的代码)吗?
  • 我认为你需要进入函数,然后看看变量是什么样的。
  • C 不支持方法。只有函数。
  • 在调用该函数之前是否声明了 VLA?
  • @Andy Schweig:那是相当多的初始化代码,但是当我展示 gdb 的 sysout 时,它们在跳入函数之前都充满了有用的数据。

标签: c linux segmentation-fault


【解决方案1】:

我已经很久没有使用过 HP/UX,但模糊地记得以下建议:

确保您正确初始化变量/支柱。使用 calloc 而不是 malloc。

也不要假设特定的位模式顺序:例如低字节然后高字节。机器的 Ska 字节序。编译器中通常有宏会为您处理适当的排序。

【讨论】:

    【解决方案2】:

    更新 15.10.16

    在调试了更多小时后,我发现了真正的问题。在方法“sequenznummernabgleich”的第一行是一个结构的声明

    TS_TEL_TAB tel_tab_S01;
    

    定义如下:

    typedef struct {
       TS_BOF_REC   bof;
       TS_REM_REC   rem;
       TS_EOF_REC   eof;
       int          bof_len;
       int          rem_len;
       int          eof_len; 
       int          cnt;     
       char         teltyp[LEN_TELTYP+1];
       TS_TEL_ENTRY entries[MAX_TEL];
    } TS_TEL_TAB;
    

    它是嵌入式结构 TS_TEL_ENTRY

    typedef struct {
       int  len;
       char tel[MAX_TEL_LEN];
    } TS_TEL_ENTRY;
    

    问题在于MAX_TEL_LEN 的值已从 512 更改为 1024,因此结构的大小几乎翻了一番,导致 STACK SIZE 不再足够大。。 p>

    解决方案 只需将堆栈大小从 8Mb 设置为 64Mb。这可以使用ulimit命令(在linux下)来实现。

    列出当前堆栈大小:ulimit -s

    将堆栈大小设置为 64Mb:ulimit -s 65535

    注意:堆栈大小的值以 kB 为单位。

    对于ulimit 命令的简短参考,请查看@ss64

    【讨论】:

    • XY 解决方案。虽然它首先解决了问题,但这是错误的方法。就像你有一个爆胎并把滑板放在它的位置而不是修理轮胎。
    • @Olaf 内存需求变大了,所以我给了它更多。该解决方案有什么问题?
    • 我评论了问题所在。如果 Firefox 等工具使用标准堆栈,我怀疑您的程序将是一个例外。做一些研究,摆脱眼罩,
    • 正确的解决方案是使用动态内存分配(malloccalloc 等)而不是数组。 64MB 堆栈是一个可笑的“解决方案”。
    • @PaulMcKenzie 感谢您的建议。我将委托一张票来分配堆而不是堆栈上的对象,然后将堆栈大小减小回 8Mb。我在学习时学习了 C/C++ 编程,但在过去的十年里再也没有使用过它;-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-25
    • 1970-01-01
    • 2021-01-08
    • 1970-01-01
    • 2021-07-11
    • 2012-02-21
    • 1970-01-01
    相关资源
    最近更新 更多