簡體   English   中英

使用malloc從內存分配中堆損壞:為什么會發生?

[英]Heap corruption from memory allocation using malloc: why did it happen?

好的,我試圖像編程練習一樣實現memmove,當我嘗試使用malloc時,我在memmove函數中遇到了內存訪問沖突。 這是函數:

//Start

void* MYmemmove (void* destination, const void* source, size_t num) { 

    int* midbuf = (int *) malloc(num); // This is where the access violation happens.
    int* refdes = (int *) destination; // A pointer to destination, except it is casted to int*
    int* refsrc = (int *) source; // Same, except with source
    for (int i = 0;num >= i;i++) { 
        midbuf[i] = *(refsrc + i); // Copy source to midbuf
    }
    for (int i = 0;num >= i;i++) { 
        refdes[i] = *(midbuf + i); // Copy midbuf to destination
    } 
    free(midbuf); // free midbuf 
    refdes = NULL; // Make refdes not point to destination anymore
    refsrc = NULL; // Make refsrc not point to source anymore
    return destination;
}

順便說一句,我是指針的新手,所以如果有一些錯誤,請不要感到驚訝。 我究竟做錯了什么?

請注意其他建議! 答案取決於如何使用記憶。 其他答案指出,您應該更改malloc調用以考慮int的大小。 但是,如果將您的memmove函數用於表示“移動此字節數”,則實現將是錯誤的。 相反,我將繼續使用char *,因為它可以一次性解決多個問題。

另外,一個int通常為4個字節,而char通常為1個字節。 如果收到的void*地址不是字對齊的(不是4個字節的倍數),則將出現問題:要復制一個非字對齊的int,您將需要進行多次讀取和昂貴的位屏蔽。 這是低效的。

最終,發生內存訪問沖突,因為您每次都增加了midbuf int指針,並且一次向前移動了4個字節 但是,您僅分配了num 個字節 ,因此最終將嘗試訪問分配的區域末尾的內容。

/** Moves num bytes(!) from source to destination */
void* MYmemmove (void* destination, const void* source, size_t num) { 

    // transfer buffer to account for memory aliasing
    // http://en.wikipedia.org/wiki/Aliasing_%28computing%29
    char * midbuf = (char *) malloc(num); // malloc allocates in bytes(!)
    char * refdes = (char *) destination;
    char * refsrc = (char *) source;

    for (int i = 0; i < num; i++) { 
        midbuf[i] = *(refsrc + i); // Copy source to midbuf
    }

    for (int i = 0; i < num; i++) { 
        refdes[i] = *(midbuf + i); // Copy midbuf to destination
    } 

    free(midbuf); // free midbuf
    // no need to set the pointers to NULL here.
    return destination;
}

通過逐字節復制,可以避免對齊問題,以及num本身不是4個字節的倍數的情況(例如3,因此int對於該移動太大)。

將字符串替換為malloc:

int* midbuf = (int *) malloc(num*sizeof(int)); 

問題是,你不分配num INT但元素num字節。

int* midbuf = (int *) malloc(num); // This is where the access violation happens.
int* refdes = (int *) destination; // A pointer to destination, except it is casted to int*
int* refsrc = (int *) source; // Same, except with source
for (int i = 0;num >= i;i++) { 
    midbuf[i] = *(refsrc + i); // Copy source to midbuf
}

mallocnum個字節,但在循環中,您嘗試復制num int秒。 由於int通常占用一個以上的字節,因此您訪問的范圍超出限制。

內存訪問沖突?

您正在嘗試訪問您無權訪問的內存。 也許您有一個空指針,或者該指針指向另一個程序或代碼段。

問題是,你mallocing num字節到midbuf ,然后復制num整數進去。 由於在大多數平台上int都大於字節,因此您遇到了問題。 將您的malloc更改為num*sizeof(int) ,您將不會遇到此問題。

有兩個問題需要研究

1.內存空間

(前提是MYmemmove了自定義實現以按問題提示移動ints

    int* midbuf = (int *) malloc(num * sizeof(int));

malloc基於字節,並且將分配num個字節。 int *是一個指向ints的指針。 意味着midbuf[x]將通過midbuf + sizeof(int)*x訪問內存。 您要改為分配num intsints的大小取決於體系結構,通常為4或2個字節)。 因此, malloc(num * sizeof(int))

2.數組索引

    for (int i = 0;num > i;i++) { 

在C(和C ++)數組中,數組是從0開始的,即第一個索引是0 你做對了。 但這也意味着,如果保留num ints ,則可用索引將為0num-1 在您的循環中,由於條件num >= ii將在0num變化,這意味着您將訪問num+1項目。 因此, num > i (或i < numfor條件更好。

#include <stdlib.h>  // did you included this?


void* MYmemmove (void* destination, const void* source, size_t num) { 

    char *Source = source, *Destination = destination;
    char *Middle = malloc( sizeof(char) * num );    // midbuf

    for (int i = 0; i < num ; i++) { 
        Middle[i] = Destination[i]; // Copy source to midbuf
    }
    for (int i = 0; i < num ; i++) { 
        Destination[i] = Middle[i]; // Copy midbuf to destination
    }

    free(Middle);                   // free memory allocated previously with malloc
    return destination;
}

違反Acces可能是因為您沒有包括malloc所需的庫(如果忘記了函數定義,標准c不會在您的面前拋出錯誤)。 您不需要將指針標記為NULL,因為C中沒有垃圾回收(指針就是-指針。指向內存中某個點的地址,而不是內存本身)。

考慮像這樣的指針

指針的地址0x1243 0x4221地址-> {某種數據}

目標= 0x1243 *目標=當前地址為0x4221的任何值

您也不能索引空指針。 您必須首先將它們轉換為某種類型,以便編譯器知道它們需要多少偏移量。

Destination [x] = *(Destination + x)

一個char是1個字節,所以char指針實際上將被移動x個字節,但是一個int是4個字節,並且一個int指針將被移動4 * x個字節。 如果聽起來很技術,請不要太擔心,當您掌握到很低的水平時,這將很重要;)

暫無
暫無

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

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