传递给 free() 的指针必须指向内存块的开头,还是可以指向内部?

发布于 2024-10-09 21:01:33 字数 895 浏览 11 评论 0原文

问题就在标题中......我搜索了但找不到任何东西。


编辑:

我真的认为没有必要解释这一点,但是因为人们认为我所说的没有意义(而且我问了错误的问题),所以问题是:

因为人们似乎对所有问题的“根本”原因而不是所提出的实际问题非常感兴趣(因为这显然有助于更好地解决问题,让我们看看它是否确实如此),问题是:

我试图使基于 NTDLL.dll 的 D 运行时库,以便我可以将该库用于 Win32 子系统以外的子系统。所以这迫使我只能链接 NTDLL.dll。

是的,我知道这些函数是“未记录的”,并且可能随时更改(尽管我打赌 wcstombs 仍然会执行相同的操作准确 20 年后的事情,如果它仍然存在的话)。是的,我知道人们(尤其是微软)不喜欢开发人员链接到该库,而且我可能会因为这里受到批评。是的,以上两点意味着在 Win32 子系统之前运行的 chkdsk 和碎片整理程序等程序根本不应该被创建,因为它实际上不可能与 kernel32 之类的东西链接.dll 或 msvcrt.dll 并且仍然具有 NT 本机可执行文件,因此我们开发人员应该假装这些阶段永远超出我们的能力范围。

但是,我怀疑这里有人希望我粘贴几千行代码并帮助我查看它们并尝试找出为什么没有失败的内存分配被拒绝我正在修改的源代码。因此,这就是为什么我问了一个与“根本”原因不同的问题,尽管这被认为是社区的最佳实践。

如果仍然不明白,请随时在下面发表评论! :)


编辑 2:

经过大约 8 个小时的调试,我终于发现了问题:

事实证明,RtlReAllocateHeap() 确实不会RtlAllocateHeap( ) 如果给它的指针是NULL

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.

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.

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:

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

我一向站在原地 2024-10-16 21:01:33

它必须指向块的开头。将空指针传递给 free() 是安全的,但传递任何未由 malloc() 或其亲属之一分配的指针将导致未定义的行为。有些系统会给你一个运行时错误 - 类似“未分配指针的释放”的内容。

编辑:

我编写了一个测试程序来获取错误消息。在我的机器上,该程序:

#include <stdlib.h>

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

  free(x);

  return 0;
}

崩溃并显示以下消息:

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

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".

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
是你 2024-10-16 21:01:33

您可以传递给free唯一东西是从malloc(或calloccalloc)返回给您的指针>realloc 等),或 NULL。

我猜你问这个问题是因为你有一些执行 malloc 的函数,并且你想弄乱数据块,然后在完成后将其删除,并且你不想费心保留原始指针的副本。事实并非如此。

The only thing you can pass to free is a pointer returned to you from malloc (or calloc, realloc, etc), or 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.

烦人精 2024-10-16 21:01:33

从您添加到现有答案的评论来看,您似乎提出了错误的问题。如果您需要内存对齐,为什么不问这个问题呢?询问根本问题,而不是询问您认为的解决方案!

因此,如果您不介意,我将回答您应该问的问题:

Aligned memory Allocation issupported in Win32 by _aligned_malloc()。它或多或少相当于 POSIX memalign()

如果您需要对齐分配的实现,实现起来相当简单:

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 ) ;
}

alignment 参数必须是 2 的幂。

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()

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.

三月梨花 2024-10-16 21:01:33

FWIW,上次我研究 C 运行时库如何与 mallocfree 一起工作时,malloc 为您提供的块实际上有一些相对于它给你的指针的负偏移处的额外单词。这些说明了诸如块有多大之类的事情。 免费依赖于能够找到这些东西。不知道这是否有任何启发。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文