簡體   English   中英

在C程序中獲取分段錯誤

[英]Getting Segmentation Fault in C program

我在下面的代碼的第8行遇到了分段錯誤。

typedef struct _my_struct {
     int pArr[21];      
     int arr1[8191];
     int arr2[8191];
     int m;
     int cLen;
     int gArr[53];  
     int dArr[8191]; 
     int data[4096];
     int rArr[53]; 
     int eArr[1024];

};

void *populate_data(void *arg) {
1   register int mask =1, iG;
2   struct _my_struct *var ;
3   var = arg;                         // arg is passed as initialized struct variable while creating thread
4   var->m = 13;
5   var->arr2[var->m] = 0;
6   for (iG = 0; iG < var->m; iG++) {
7       var->arr2[iG] = mask;
8       var->arr1[var->arr2[iG]] = iG;
9       if (var->pArr[iG] != 0)         // pArr[]= 1011000000001
10          var->arr2[var->m] ^= mask;
11      mask <<= 1;
12  }
13  var->arr1[var->arr2[var->m]] = var->m;
14  mask >>= 1;
15  for (iG = var->m+ 1; iG < var->cLen; iG++) {
16      if (var->arr2[iG - 1] >= mask)
17          var->arr2[iG] = var->arr2[var->m] ^ ((var->arr2[iG- 1] ^ mask) << 1);
18      else
19          var->arr2[iG] = var->arr2[iG- 1] << 1;
20      var->arr1[var->arr2[iG]] = iG;
21  }
22  var->arr1[0] = -1;
   }

這是線程函數:

void main() {
        unsigned int tid;

        struct _my_struct  *instance = NULL;
        instance = (struct _my_struct  *)malloc(sizeof(_my_struct ));

        start_thread(&tid , 119312, populate_data, instance );          
}

int 
start_thread(unsigned int *tid, int stack_size, void * (*my_function)(void *), void *arg)
{
        pthread_t ptid = -1;
        pthread_attr_t pattrib;

        pthread_attr_init(&pattrib);

        if(stack_size > 0)
        {
            pthread_attr_setstacksize(&pattrib, stack_size);
        }
        else
        {
            pthread_attr_destroy(&pattrib);
            return -1;
        }

        pthread_create(&ptid, &pattrib, my_function, arg);      
        pthread_attr_destroy(&pattrib);

        return 0;
}

通過gdb調試后,出現此錯誤,

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffdfec80700 (LWP 22985)]
0x0000000000401034 in populate_data (arg=0x7fffffffe5d8) at Queue.c:19
19                     var->arr1[var->arr2[iG]] = iG;

它的回溯是:

#0  0x0000000000401034 in populate_data (arg=0x7fffffffe5d8) at Queue.c:159
#1  0x00007ffff7bc6971 in start_thread () from /lib/libpthread.so.0
#2  0x00007ffff792292d in clone () from /lib/libc.so.6
#3  0x0000000000000000 in ?? ()

但是,我無法糾正該錯誤。

真的很感謝Anyhelp。

請在start_thread顯示調用代碼。

似乎可能是堆棧和/或內存分配錯誤,該結構相當大(假設32位int 8 MB),並且很可能會溢出某些堆棧限制。

甚至有可能超出了范圍,這就是為什么必須顯示調用步驟的原因。

我不知道您是否可能更改了_my_struct中的數組名稱以隱藏它們的用途(也許是公司的機密信息?),但是如果這實際上就是您為數組命名的名稱,我只是建議您給它們起一個有意義的名字,即當某人從現在起四年后必須閱讀您的代碼時,他們會有一些希望遵循您的初始化循環並了解正在發生的事情。 循環變量iG

我的下一個評論/問題是,為什么要觸發一個線程來初始化主線程堆棧上的該結構? 初始化后,哪個線程將使用此結構? 還是要使其他線程使用它? 您是否有任何機制(互斥量或信號量?)來確保其他線程在初始化線程完成初始化之前不會開始使用數據? 什么樣的問題引起了您的興趣,您為什么要煩惱先觸發一個單獨的線程來初始化它? 您可以直接從main()直接調用populate_data()對其進行初始化,而不必擔心同步,因為在完成初始化之前,您甚至不需要啟動任何其他線程。 如果您在多核計算機上運行,​​則在main()進行並執行其他操作時觸發該單獨的線程來進行初始化可能會從中獲得一些小好處,但是會從您的結構大小(不是很小,但不是兩者都是巨大的),看來好處將微乎其微。 而且,如果您在單個內核上運行,則根本不會獲得並發優勢。 由於上下文切換的開銷,您只是在浪費時間觸發另一個線程來執行此操作; 在單核環境中,最好直接從main()調用populate_data()。

下一個評論是,您的_my_struct並不龐大,因此它不會自己丟掉堆棧。 但這也不小。 如果您的應用始終只需要此結構的一個副本,則也許應將其設為全局變量或文件作用域變量,以免占用堆棧空間。

最后,到您的實際錯誤.........

我沒有費力嘗試破譯您的加密循環代碼,但是valgrind告訴我您有一些條件取決於未初始化的位置:

~/test/so$ valgrind a.out
==27663== Memcheck, a memory error detector
==27663== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==27663== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==27663== Command: a.out
==27663==
==27663== Thread 2:
==27663== Conditional jump or move depends on uninitialised value(s)
==27663==    at 0x8048577: populate_data (so2.c:34)
==27663==    by 0x593851: start_thread (in /lib/libpthread-2.5.so)
==27663==    by 0x4BDA8D: clone (in /lib/libc-2.5.so)
==27663==
==27663== Conditional jump or move depends on uninitialised value(s)
==27663==    at 0x804868A: populate_data (so2.c:40)
==27663==    by 0x593851: start_thread (in /lib/libpthread-2.5.so)
==27663==    by 0x4BDA8D: clone (in /lib/libc-2.5.so)

我的so2.c第34行與上述代碼中的第9行相對應。 我的so2.c第40行與上面代碼發布中的第15行相對應。

如果將以下內容添加到populate_data()的頂部,這些valgrind錯誤將消失:

memset(arg,0,sizeof(_my_struct_t));

(我對您的結構定義進行了如下修改:)

typedef struct _my_struct { int pArr[21]; ......... } _my_struct_t;

現在,僅僅因為添加memset()調用使錯誤消失就不一定意味着您的循環邏輯是正確的,僅意味着現在這些位置被valgrind視為“已初始化”。 如果您的邏輯需要在初始化循環開始時在這些位置具有全零,那么應該可以解決此問題。 但是您需要親自驗證這確實是正確的解決方案。

順便說一句...有人建議使用calloc()獲得歸零的分配(而不是使用臟堆棧空間)...也可以,但是如果您希望populate_data()非常安全,則可以將內存歸零在其中,而不是在調用方中,因為(假設您喜歡初始化邏輯),populate_data()取決於將其清零,所以main()不必關心它是否為零。 兩種方式都不大。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM