[英]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.