[英]Memory address truncation issue during dynamic memory allocation
我有一个 fortran 子例程 (getmem.F),它使用 C 程序 (memalloc.c) 进行动态 memory 分配。 以下子例程和函数是用于研究目的的非常古老的大型代码的一部分。 我在 64 位机器上编译,我使用的是 PGI 编译器 2020.4 版本。 以下是fortran代码。
subroutine getmem(ptr, size)
c-----get pointered memory
cdir$ nolist
include 'common.h'
include 'inputcom.h'
cdir$ list
integer memalloc, memfree
integer ptr, size, ierr0
c-----allocate 'size' words of memory and send back pointer in 'ptr'
print *, "Value of ptr and size before memory allocation"
print *, "ptr:", ptr ! The value of ptr is 0
print *, "size:", size ! The value of size is 1138280
if (size .lt. 0) then
ierr0 = memfree (ptr)
else
ierr0 = memalloc (ptr, size)
endif
print *, "Value of ptr and size after memory allocation"
print *, "ptr:", ptr ! The value of ptr is -1431465968 (This is incorrect
! value which is the decimal from signed 2's complement for 2863501328)
print *, "size:", size ! The value of size is 1138280
if (ierr0 .ne. 0) then
call writemsg ('Unable to get memory.')
write (buffer, 100) size
100 format ('GETMEM: size is ', i15, '.')
call writemsg (buffer)
stop 'getmem'
endif
return
end
这里是 C 代码 memalloc.c
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h> /* Added by Surya */
int memalloc_ (int *nextptr, int *size)
{
void *ptr;
printf("Address of nextptr:%p \nValue of nextptr: %d \n", nextptr, *nextptr);
/*Output: Address of nextptr: 0x1687ad0
Value of nextptr: 0 */
/* Before Memory Allocation */
printf("Address pointed by ptr (Value stored in ptr): %p \n", (void*)ptr);
/*Output: Address pointed by ptr (Value stored in ptr): 0x7fffffff8b40 */
if (*nextptr == NULL) {
if ((ptr = (void *) malloc (*size)) == NULL) {
return(-1);
}
}
else {
if ((ptr = (void *) realloc (*nextptr, *size)) == NULL) {
return(-1);
}
}
/* After memory allocation using malloc() */
printf("Address pointed by ptr (Value stored in ptr): %p \nValue when printed as a long integer %ld \n", (void*)ptr, (int*)ptr);
/* Output: Address pointed by ptr (Value stored in ptr): 0x2aaaaaad9010
Value when printed as a long integer: 46912496308240 */
*nextptr = (int) ptr;
printf("Address of nextptr:%p \nValue of nextptr: %d \n", nextptr, *nextptr);
/* Output: Address of nextptr: 0x1687ad0
Value of nextptr: -1431465968 */
printf("Value of nextptr in long format: %ld \n", *nextptr);
/* Output: Value of nextptr in long format: 2863501328 */
return (0);
}
当我进行十六进制到十进制转换(反之亦然)时( https://www.rapidtables.com/convert/number/hex-to-decimal.html ),我注意到了问题所在。 当我们做 (int) ptr. ptr = 0x2aaaaaad9010(十进制值为46912496308240)的十六进制值被截断为aaad9010(十进制值为2863501328)。 当它作为 ptr 传递回 fortran77 代码时,稍后用作指向 memory 的指针的 ptr 无法找到变量及其值。 如何解决此问题,以便 C 程序中不会发生截断?
PS 这是一种非常古老的编码风格,但它是我研究的一个更大的代码(通过实验验证)的一部分。
(int) ptr
cast 是不可移植的,并且很明显是缩小转换的罪魁祸首。ptr
的内容分配给某个地方之前,您不能打印它。 在赋值之前不能打印nextptr
指向的内容。 您不能打印 null 指针的值。size
作为指针传递,因为您没有在 function 内部更改它。malloc
的结果转换为void*
是没有意义的。void*
转换为void*
是没有意义的。realloc
的行为类似于malloc
。 由于您的 function 显然假定在第一次调用期间传递的指针始终初始化为 null 指针,因此您可以利用它来简化代码。realloc
。删除所有错误和混乱后,您的代码可能如下所示:
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
// NOTE: *nextptr must be initialized to null outside this function!
int memalloc_ (int** nextptr, int size)
{
void *ptr;
printf("Address of *nextptr:%p\n", (void*)*nextptr);
ptr = realloc(*nextptr, size);
if (ptr == NULL) {
return -1;
}
*nextptr = ptr;
printf("Address pointed by ptr (Value stored in ptr): %p\n", ptr);
printf("Address of nextptr:%p\n", (void*)*nextptr);
return 0;
}
即使在旧的 C90 中也应该可以编译。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.