2012-02-03 47 views
3

我的程序中有一個小的內存訪問問題,我沒有找到錯誤,也許有人可以幫助我。在2D數組中寫入分段錯誤

我創建了一個新類型來存儲rgb顏色值。 這種類型的樣子:

typedef struct pixel { 
    unsigned char r; 
    unsigned char g; 
    unsigned char b; 
} pixel; 

在我的主程序我用calloc創建二維數組動態,存儲紅色信息的。

pixel **pixelvalue = (pixel **) calloc(imginformation.width, sizeof(pixel)); 
for (i = 0; i < imginformation.width; i++) { 
    pixelvalue[i] = (pixel *) calloc(imginformation.height, sizeof(pixel)); 
} 

之後,我打電話給我的函數,它讀取顏色值和誰應該安全的數組。該函數作爲數組的參數獲取。

ReadFile(file, imginformation (Stuff like height and so one), pixelvalue (The calloc array)); 

在這個函數我試圖與

pixelvalue[i][j].r = (unsigned char)fgetc(in); 

在這裏,我得到了內存訪問錯誤寫的價值觀,我是怎麼了?

編輯

你好,首先抱歉缺少語言,我有點累了昨天:)。

爲了理解,我創建了一個像素數組,並且元素指向另一個像素數組?像[Point to another 1D array pixel]

使用像素**pixelvalue = calloc(imginformation.width, sizeof(pixel *));我創建了imginformation.width類型爲像素的指針數,每個指針都顯示爲像素,對嗎?

如果你能解釋一點點,如果我錯了,那將是非常棒的。我真的很想理解它。

@卡爾Norum時你是什麼意思有:

「你不應該鑄造釋放calloc的(返回值),這樣做可以 用#include隱藏的錯誤,可能回來咬你走下了 路「。

?我使用alloc空間作爲函數的參數,而不是返回值。

感謝您的幫助!

格爾茨

回答

3

你不是實拍二維數組,你正在做的是指向像素數組指針數組。這意味着,你的第一個電話calloc應當爲指針像素分配足夠的空間,而不是:

pixel **pixelvalue = calloc(imginformation.width, sizeof(pixel *)); 

你沒有用標記語言你的問題,但假設這是C(根據你的typedef,這將不會是在C++中是必要的),你不應該鑄造calloc()的返回值。這樣做可以隱藏與#include,可能會回來咬你的道路上的錯誤。

編輯:

你問一對夫婦的後續問題。第一個問題已經被其他答案解答得很好,我想,但我會盡量總結。你分配的方式,你首先要分配一個指針數組 - 每個指針將指向你的數組的一行。然後需要分配行本身 - 每個對象的空間都會到達那裏,並且指向行的指針存儲在第一個指針數組中。

你的第二個問題,從calloc()返回值是非常簡單的。如果您施放返回值,則可以隱藏自己的隱式聲明錯誤。由於calloc返回類型爲void *,如果你這樣做:

my_ptr = calloc(1, 2); 

一切都很好地工作。現在想象一下,您沒有包含stdlib.h,因此您的翻譯部門中沒有原型calloc()。這會導致編譯器將calloc()的簽名假定爲int calloc(int, int),這是不正確的。上面的同一行代碼會給你一個關於爲該函數默認簽名的警告。使用類似於你的代碼中的類型轉換會掩蓋該警告,並且你可能永遠不會知道你錯過了那條線。

+0

嗨,謝謝你的解決方案正常工作。現在我有一些理解問題,看我編輯。謝謝。 – hofmeister 2012-02-03 08:53:03

+0

@Taz - 我會編輯以解決您的修改一時。 – 2012-02-03 18:44:31

0

代碼

pixel **pixelvalue = (pixel **) calloc(imginformation.width, sizeof(pixel)); 

pixelvalue是一個指針的指針像素 - 你的typedef。

你需要寫

pixel **pixelvalue = calloc(imginformation.width, sizeof(pixel *)); 

代替。

+0

是的,你的權利以及@ carl-norum。請看我**編輯**,我的理解正確嗎? – hofmeister 2012-02-03 08:56:10

1

請參閱圖一個交代enter image description here

所以,你首先創建的pixel *使用釋放calloc數組。使用callocpixel填充該數組。

+0

謝謝,這幫了很大的忙!所以首先我要創建所有的指針,例如高度和每個元素都顯示爲寬度的像素。謝謝! – hofmeister 2012-02-03 09:41:57

+0

塔茲 - 它有助於使用diagran來理順你的想法 – 2012-02-03 23:39:12

0

其他海報已經正確識別出您應該以pixel*爲單位而不是以pixel爲單位分配您的第一塊內存。

但爲什麼這個問題會導致段錯誤?

在32位機器上,上面定義的像素結構需要3個字節,但指針需要32位(4個字節)。

也就是說,

  • sizeof(pixel) == 3
  • sizeof(pixel*) == 4

所以你只分配你需要的內存的75%。在訪問圖像的底部四分之一時,您將訪問您從未分配過的內存。

(在一些64位平臺上,問題肯定只會變得更糟。在一些16位平臺上,雖然它仍然很渺茫,但你也許能夠擺脫這種困境)

+0

但是,如果我使用像素的指針一切都很好? – hofmeister 2012-02-03 09:40:58

+0

是的,應該。你明白爲什麼會出現這個問題,對嗎? (見Ed Heal的精細圖) – 2012-02-03 09:50:58

+0

是的,我做過。謝謝你們! – hofmeister 2012-02-03 10:51:24