簡體   English   中英

使用-O3與g ++進行編譯時,C ++程序中出現分段錯誤

[英]Segmentation fault in a C++ program when compiling with g++ using -O3

當我使用g ++(版本4.9.1)編譯以下代碼時,對於非優化或使用-O2的優化,它可以正常工作。 但是,使用-O3進行編譯時,該程序在第30行崩潰,並顯示“分段錯誤(內核已轉儲)”。

我試圖使這一過程盡可能簡單。 我還注意到,刪除(看似)不重要的部分,例如成員變量詞,似乎可以解決問題。 我在這里做錯了什么?

#include <iostream>
#include <stdlib.h>
using namespace std;

char *curMemPos2=NULL;  //The first free pos in allocated memory

class Dictionary{
    public:
        int numWords;
        int* words;
        double* wordFrequency;
        Dictionary(int nw){
            numWords = nw;
            wordFrequency = NULL;
            wordFrequency = (double*)curMemPos2;
            curMemPos2 += (sizeof(double)*numWords);

            words = NULL;
            words = (int*)curMemPos2;
            curMemPos2 += (sizeof(int)*numWords);

            if (wordFrequency == NULL || words == NULL) {
                cout << "could not allocate memory" << endl;
                exit(0);
            }
        }

        void addwords(){
            for (int i = 0; i < numWords; i++){
                wordFrequency[i] = i * 0.2;
            }
        }
};

int main(){ 
    curMemPos2 = (char*) malloc(1024 * 1024);

    if (curMemPos2 == NULL) {
        cout << "could not allocate initial memory" << endl;
        exit(0);
    }

    for (int i = 5; i < 10; i++){
        cout << "--------------------------" << endl;
        cout << "initializing dict with " << i << " words" << endl;
        Dictionary d = Dictionary(i);
        cout << "adding words" << endl;
        d.addwords();
    }
}

您似乎在這里嘗試做一個基於內存池的分配器,這通常不是一個壞主意。 (不過,該實現可能需要進行很多改進。)

您遇到的問題是對齊。 int可能是4字節對齊的。 double可能是8字節對齊的。

對於具有基本對齊要求的任何類型的對象, malloc返回的地址始終會進行適當的對齊-因此,對於intdouble ,它始終會進行良好的對齊。 當您嘗試分配奇數個int時,會發生此問題。 假設malloc返回地址0x3000並且您分配了五個int ,然后curMemPos2的地址變為0x3014 ,然后您嘗試分配了五個double -但是0x3014不是有效的double地址,因為它不是8字節對齊。

它不能與優化一起工作,而不能與優化一起工作,這表明您的代碼中存在一些未定義的行為,這在某些情況下(不幸地)起作用了。

您在這里有幾個候選人:

  • 如果兩個不同類型的指針(例如int *wordsdouble *wordfrequency )指向相同的內存位置,則不會使用嚴格的別名 嚴格的別名是關於編譯器對指針所做的假設,以便進一步優化代碼。
  • 您添加到全局curMemPos2指針,有時為sizeof(int)有時為sizeof(double) 即使您的初始指針可能符合所有類型的對齊方式,如果優化程序嘗試使用具有對齊方式要求的特殊cpu操作,您的cumMemPos2也可能不符合double導致錯誤的對齊方式要求。
  • 您自己制定的分配方案無法控制上限:您將永遠增加curMemPos2並且您的指針可能有一天指向未分配的內存(此處沒有任何內容將其設置為NULL)。 但是好吧,這不是您的問題的根源,因為您只分配了幾個條目。

意見建議:

由於每個Dictionary結構在自我管理的內存池中都使用numwords intnumwords double ,因此我建議使用受保護的結構:

class Dictionary{
    protected: 
        struct mbloc {     // with a struct, the compiler takes care of alignment requ.
            double frequency; 
            int words; 
            };            
    public:
         ...   // allocate mbloc *entries instead of *int and *doubles; 
}; 

通過這種方法,您可以考慮使用new分配干凈的mbloc數組,甚至分配vector<mbloc>

暫無
暫無

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

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