傳遞給free()的指針是否必須指向內存塊的開頭,還是指向內部?

[英]Does the pointer passed to free() have to point to beginning of the memory block, or can it point to the interior?


The question is in the title... I searched but couldn't find anything.

問題在於標題......我搜索但找不到任何東西。


Edit:

編輯:

I don't really see any need to explain this, but because people think that what I'm saying makes no sense (and that I'm asking the wrong questions), here's the problem:

我真的沒有必要解釋這個問題,但是因為人們認為我說的話毫無意義(我問的是錯誤的問題),這就是問題所在:

Since people seem to be very interested in the "root" cause of all the problem rather than the actual question asked (since that apparently helps things get solved better, let's see if it does), here's the problem:

由於人們似乎對所有問題的“根”原因非常感興趣而不是實際提出的問題(因為這顯然有助於事情得到更好的解決,讓我們看看它是否確實如此),這就是問題所在:

I'm trying to make a D runtime library based on NTDLL.dll, so that I can use that library for subsystems other than the Win32 subsystem. So that forces me to only link with NTDLL.dll.

我正在嘗試基於NTDLL.dll創建一個D運行時庫,這樣我就可以將該庫用於Win32子系統以外的子系統。所以這迫使我只與NTDLL.dll鏈接。

Yes, I'm aware that the functions are "undocumented" and could change at any time (even though I'd bet a hundred dollars that wcstombs will still do the same exact thing 20 years from now, if it still exists). Yes, I know people (especially Microsoft) don't like developers linking to that library, and that I'll probably get criticized for the right here. And yes, those two points above mean that programs like chkdsk and defragmenters that run before the Win32 subsystem aren't even supposed to be created in the first place, because it's literally impossible to link with anything like kernel32.dll or msvcrt.dll and still have NT-native executables, so we developers should just pretend that those stages are meant to be forever out of our reaches.

是的,我知道這些功能是“無證件”的,並且隨時都可能發生變化(即使我打賭一百美元,wcstombs在20年后仍會做同樣的事情,如果它仍然存在的話)。是的,我知道人們(尤其是微軟)不喜歡開發人員鏈接到該庫,並且我可能會因此而受到批評。是的,上述兩點意味着在Win32子系統之前運行的程序如chkdsk和碎片整理程序甚至不應該首先創建,因為它幾乎不可能與kernel32.dll或msvcrt.dll之類的東西鏈接。仍然有NT本地可執行文件,所以我們開發人員應該假裝這些階段是永遠不在我們的范圍之內。

But no, I doubt that anyone here would like me to paste a few thousand lines of code and help me look through them and try to figure out why memory allocations that aren't failing are being rejected by the source code I'm modifying. So that's why I asked about a different problem than the "root" cause, even though that's supposedly known to be the best practice by the community.

但不,我懷疑這里的任何人都希望我粘貼幾千行代碼並幫助我瀏覽它們並試圖弄清楚為什么未修改的內存分配被我正在修改的源代碼拒絕。所以這就是為什么我問起一個不同於“根”原因的問題,即使這被認為是社區的最佳實踐。

If things still don't make sense, feel free to post comments below! :)

如果事情仍然沒有意義,請隨時在下面發表評論! :)


Edit 2:

編輯2:

After around ~8 hours of debugging, I finally found the problem:

經過大約8個小時的調試,我終於找到了問題:

It turns out that RtlReAllocateHeap() does not automatically work like RtlAllocateHeap() if the pointer given to it is NULL.

事實證明,如果給它的指針是NULL,RtlReAllocateHeap()不會像RtlAllocateHeap()那樣自動工作。

4 个解决方案

#1


11  

It has to point to the beginning of the block. It's safe to pass a null pointer to free(), but passing any pointer not allocated by malloc() or one of its relatives will cause undefined behaviour. Some systems will give you a runtime error - something along the lines of "Deallocation of a pointer not malloced".

它必須指向塊的開頭。將空指針傳遞給free()是安全的,但傳遞未由malloc()或其某個親屬分配的任何指針都將導致未定義的行為。有些系統會給你一個運行時錯誤 - 就像“釋放未指向malloced的指針”那樣。

Edit:

編輯:

I wrote a test program to get the error message. On my machine, this program:

我寫了一個測試程序來獲取錯誤信息。在我的機器上,這個程序:

#include <stdlib.h>

int main(int argc, char **argv)
{
  int *x = malloc(12);
  x++;

  free(x);

  return 0;
}

Crashes with this message:

與此消息崩潰:

app(31550) malloc: *** error for object 0x100100084: pointer being freed was not allocated

#2


4  

The only thing you can pass to free is a pointer returned to you from malloc (or calloc, realloc, etc), or NULL.

你可以傳遞給free的唯一東西是從malloc(或calloc,realloc等)返回給你的指針,或NULL。

I'm guessing you're asking because you have some function where you do a malloc, and you want to mess with the data block and then get rid of it when you're done, and you don't want to be bothered keeping a copy of the original pointer around. It doesn't work that way.

我猜你是在問,因為你有一些功能,你做了一個malloc,你想弄亂數據塊,然后在你完成后擺脫它,你不想被打擾原始指針的副本。它不起作用。

#3


1  

From the comments you have added to existing answers, it seems you are asking the wrong question. If memory alignment is what you need, why don't you ask that question? Ask about the root problem rather than asking about your perceive solution!

從您添加到現有答案的評論中,您似乎提出了錯誤的問題。如果您需要內存對齊,為什么不問這個問題?詢問根本問題而不是詢問您的感知解決方案!

So if you don't mind I'll answer the question you should have asked:

所以如果你不介意我會回答你應該問的問題:

Aligned memory allocation is supported in Win32 by _aligned_malloc(). It is more of less equivalent to POSIX memalign()

Win32中的_aligned_malloc()支持對齊的內存分配。它更不等於POSIX memalign()

If you need an implementation of aligned allocation, it is fairly simple to implement:

如果您需要實現對齊分配,則實現起來相當簡單:

void* aligned_malloc( size_t size, size_t alignment )
{
    void* unaligned = malloc( size + alignment ) ;
    void* aligned = (void*)(((intptr_t)unaligned + alignment) & ~(alignment - 1));
    void** free_rec_ptr = ((void**)aligned - 1) ;
    *free_rec_ptr = unaligned ;

    return aligned ;
}

void aligned_free( void* block )
{
    void** free_rec_ptr = ((void**)block - 1) ;
    free( *free_rec_ptr ) ;
}

The alignment argument must be a power of two.

對齊參數必須是2的冪。

#4


0  

FWIW, the last time I looked into how the C run time library worked with malloc and free, the block that malloc gives you actually has some extra words at negative offsets relative to the pointer it gives you. These say things like how big the block is, and other stuff. free relied on being able to find those things. Don't know if that sheds any light.

FWIW,我最后一次研究C運行時庫如何使用malloc和free,malloc給你的塊實際上在相對於它給你的指針的負偏移處有一些額外的單詞。這些就像塊有多大,以及其他東西。免費依靠能夠找到那些東西。不知道這是否有任何影響。


注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2011/01/03/cd1ce5692f93ec0d35ef8b066b51e043.html



 
粤ICP备14056181号  © 2014-2021 ITdaan.com