[英]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
返回的地址始終會進行適當的對齊-因此,對於int
或double
,它始終會進行良好的對齊。 當您嘗試分配奇數個int
時,會發生此問題。 假設malloc
返回地址0x3000
並且您分配了五個int
,然后curMemPos2
的地址變為0x3014
,然后您嘗試分配了五個double
-但是0x3014
不是有效的double
地址,因為它不是8字節對齊。
它不能與優化一起工作,而不能與優化一起工作,這表明您的代碼中存在一些未定義的行為,這在某些情況下(不幸地)起作用了。
您在這里有幾個候選人:
int *words
和double *wordfrequency
)指向相同的內存位置,則不會使用嚴格的別名 。 嚴格的別名是關於編譯器對指針所做的假設,以便進一步優化代碼。 curMemPos2
指針,有時為sizeof(int)
有時為sizeof(double)
。 即使您的初始指針可能符合所有類型的對齊方式,如果優化程序嘗試使用具有對齊方式要求的特殊cpu操作,您的cumMemPos2
也可能不符合double
導致錯誤的對齊方式要求。 curMemPos2
並且您的指針可能有一天指向未分配的內存(此處沒有任何內容將其設置為NULL)。 但是好吧,這不是您的問題的根源,因為您只分配了幾個條目。 意見建議:
由於每個Dictionary
結構在自我管理的內存池中都使用numwords int
和numwords 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.