【问题标题】:C - sbrk(size) returns valid pointer but sbrk(0) is negative valueC - sbrk(size) 返回有效指针但 sbrk(0) 为负值
【发布时间】:2017-03-07 01:11:40
【问题描述】:

我的分配代码是

dat* data = NULL;
data = sbrk(SIZE);
if((int) data != -1){
   return data
}else{
  printf("Not enough space");
}

sbrk(...) 函数返回一个有效地址 (0x603021),但是当我进入 gdb 并打印 sbrk(0) 时,我得到了十六进制值 0xffffffff8060341。经过数学计算,我发现指针 0x8060341 应该是 sbrk(0)。前面的字母f(即0xfffff...)是哪里来的?

【问题讨论】:

  • 你能告诉我们确切你做了什么吗?您准确地获得了您所询问的价值吗?
  • 更确切地说,您是如何获得0xffffffff8060341 的价值的?看起来您可能在某处涉及到标志扩展。也许你还有其他奇怪的(int) 演员?您当前发布的代码中的那个在 64 位拱门上肯定是无效的。
  • 另外,您是否正确包含unistd.h 和/或编译时带有警告?您的问题可能是由 sbrk 隐式声明为 int (*)(int) 引起的。
  • 在 gdb 中调试时,我只是输入了 - p (void*) sbrk(0) - 并且还声明了 unistd.h
  • 不要描述你做了什么 - 展示一个简短的工作程序和一个 gdb 会话的记录来证明问题。

标签: c pointers memory-management memory-leaks sbrk


【解决方案1】:

gdb 向您显示内存段的完整 64 位地址。十六进制的 64 位地址需要总共 16 个十六进制数字 (0-9,A-F) 才能完全指定。从每位数 64 位/4 位 = 16。

如果您看到的更少,那是因为编辑器正在截断内存地址的前 32 位(8 个十六进制数字),只显示剩余的或更低的 8 个。这是 32 位计算世界的遗留物,其中 8 个十六进制数字足以完全指定内存地址。

【讨论】:

  • 但是对于 sbrk(0),地址应该是 0x000000008060341 而不是 0xffffffff8060341
  • sbrk(0) 是否返回 -1 作为错误指示符?是否在 sbrk(0) 之前调用了 brk(..)?
  • brk(..) 在程序中永远不会被调用
  • 我不熟悉这些调用,也从未使用过它们。该文档建议最好避免使用它们,据我阅读,在我看来, sbrk(..) 应该首先调用 brk(...) 。文档示例位于:linux.die.net/man/2/sbrk
猜你喜欢
  • 2013-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-20
  • 2019-06-15
相关资源
最近更新 更多