Digital Mars DOS _fmalloc 没有提供指向可用内存的指针?
Digital Mars DOS _fmalloc not giving pointer to usable memory?
我正在使用 Digital Mars C 编译器在小内存模型中编写一个 16 位 DOS 程序。这个程序需要将一个文件保存到硬盘中,它还需要在内存中分配64000字节来临时存储数据,以备将它和其他一些数据一起保存到硬盘中。问题是它在不应该的情况下将乱码保存到文件中。我做了一个单独的小程序,这样我就可以将我可能有错误的代码与不应该有任何问题的代码分开。到目前为止,我已经能够将问题追溯到 Digital Mars 中的 _fmalloc()
函数。当我写入已分配给 _fmalloc()
的数据时,数据会被程序数据损坏。当我从堆栈中分配内存时,没有问题,程序按预期工作。
.
.
文件测试程序
这是我编写的小程序,用于排除我的代码中可能存在的问题并找出问题所在。
#include <io.h>
#include <sys\stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
int main(int argc, char *argv[])
{
//unsigned char data[256]; <-- using this way works just fine
unsigned char __far *data; <-- this way does not work
data = _fmalloc(256);
if(data==NULL)
{
printf("Not enough memory.\n");
exit(1);
}
//initialize data to 1
_fmemset(data, 1, 256);
int file; //file handle
unsigned int err = 0;
// Create File
file = _creat("file.bin", _S_IREAD | _S_IWRITE);
if(file==-1){
printf("Error creating file.\n");
exit(1);
}else{
printf("File created successfully.\n");
err = 0;
}
// Write Data to File
int bytes_written = 0;
bytes_written = _write(file, &data, 256);
if(bytes_written==-1){
printf("Error writing to file.\n");
exit(1);
}else{
if(bytes_written == 256){
printf("File written successfully.\n");
err = 0;
}else{
printf("Error wrong amount of data written.\n");
exit(1);
}
}
// Close File
err = _close(file);
if(err==-1){
printf("Error closing file.\n");
exit(1);
}else{
printf("File closed.\n");
}
_ffree(data);
return 0;
}
.
.
文件输出
.
.
使用 data[256];
输出应该是这样的。总共 256 个字节。
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
01 01 01
使用data = _fmalloc(256);
不布埃诺!请注意,这还会产生一个额外的字节,总计 257 个字节。
00 00 38 14 00 01 05 00 00 00 00 00 00 00 E5 02 A2 01 01 00 1F 01 7E
2B 43 3A 5C 46 49 4C 45 2E 45 58 45 00 3C 00 50 41 54 48 3D 5A 3A 5C
00 43 4F 4D 53 50 45 43 3D 5A 3A 5C 43 4F 4D 4D 41 4E 44 2E 43 4F 4D
00 42 4C 41 53 54 45 52 3D 41 32 32 30 20 49 35 20 44 31 20 48 35 20
54 36 00 00 0D 0A 00 42 2B 4B 2B 62 2B 00 00 06 09 6A D4 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00
文本视图
..8...........å.¢.....~+C:\FILE.EXE.<.PATH=Z:.COMSPEC=Z:\COMMAND.COM.BLASTER=A220
I5 D1 H5
T6.....B+K+b+....jÔ.................................................................................................................................................
对于 malloc
情况,_write(file, &data, 256)
需要 _write(file, data, 256)
。它适用于自动分配的情况,因为 data
和 &data
是数组的相同地址(尽管类型不同)。
因此,我最终需要 _write() 和 _read() 函数的 _far 版本。编译器没有提供这些,所以我自己做了。如果这些看起来有点粗糙,请原谅我,但我以前从未做过这样的事情,所以这对我来说是一次很好的学习经历。这是我想出的代码。
int _fwrite(int fd, void __far *buffer, unsigned int length)
{
void *buffer_offset = 0; // used to pass the offset of buffer to _write()
unsigned int buffer_segment = 0; // used to change the value of the data segment register (DS)
unsigned long int buffer_copy = 0; // used for temporary, corruptible storage of buffer
int result = 0; // used for returning number of bytes written or an error from _write()
// store the full __far pointer buffer in buffer_copy as a 32 bit int so that we can use bitwise operators
buffer_copy = (unsigned long int)buffer;
// left shift the address stored in buffer_copy two bytes to get the offset address
buffer_offset = (void *)(buffer_copy << 16);
// right shift the address stored in buffer_copy two bytes to get the segment address
buffer_segment = buffer_copy >> 16;
// change the data segment register to the one that buffer points to so that _write() will work on far data
asm
{
push ds
mov ds,buffer_segment
}
// do the file write
result = _write(fd, buffer_offset, length);
// restore previous data segment register value so that near data can be accessed again
asm
{
pop ds
}
return result;
}
int _fread(int fd, void __far *buffer, unsigned int length)
{
void *buffer_offset = 0; // used to pass the offset of buffer to _read()
unsigned int buffer_segment = 0; // used to change the value of the data segment register (DS)
unsigned long int buffer_copy = 0; // used for temporary, corruptible storage of buffer
int result = 0; // used for returning number of bytes written or an error from _read()
// store the full __far pointer buffer in buffer_copy as a 32 bit int so that we can use bitwise operators
buffer_copy = (unsigned long int)buffer;
// left shift the address stored in buffer_copy two bytes to get the offset address
buffer_offset = (void *)(buffer_copy << 16);
// right shift the address stored in buffer_copy two bytes to get the segment address
buffer_segment = buffer_copy >> 16;
// change the data segment register to the one that buffer points to so that _read() will work on far data
asm
{
push ds
mov ds,buffer_segment
}
// do the file read
result = _read(fd, buffer_offset, length);
// restore previous data segment register value so that near data can be accessed again
asm
{
pop ds
}
return result;
}
我正在使用 Digital Mars C 编译器在小内存模型中编写一个 16 位 DOS 程序。这个程序需要将一个文件保存到硬盘中,它还需要在内存中分配64000字节来临时存储数据,以备将它和其他一些数据一起保存到硬盘中。问题是它在不应该的情况下将乱码保存到文件中。我做了一个单独的小程序,这样我就可以将我可能有错误的代码与不应该有任何问题的代码分开。到目前为止,我已经能够将问题追溯到 Digital Mars 中的 _fmalloc()
函数。当我写入已分配给 _fmalloc()
的数据时,数据会被程序数据损坏。当我从堆栈中分配内存时,没有问题,程序按预期工作。
.
.
文件测试程序
这是我编写的小程序,用于排除我的代码中可能存在的问题并找出问题所在。
#include <io.h>
#include <sys\stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
int main(int argc, char *argv[])
{
//unsigned char data[256]; <-- using this way works just fine
unsigned char __far *data; <-- this way does not work
data = _fmalloc(256);
if(data==NULL)
{
printf("Not enough memory.\n");
exit(1);
}
//initialize data to 1
_fmemset(data, 1, 256);
int file; //file handle
unsigned int err = 0;
// Create File
file = _creat("file.bin", _S_IREAD | _S_IWRITE);
if(file==-1){
printf("Error creating file.\n");
exit(1);
}else{
printf("File created successfully.\n");
err = 0;
}
// Write Data to File
int bytes_written = 0;
bytes_written = _write(file, &data, 256);
if(bytes_written==-1){
printf("Error writing to file.\n");
exit(1);
}else{
if(bytes_written == 256){
printf("File written successfully.\n");
err = 0;
}else{
printf("Error wrong amount of data written.\n");
exit(1);
}
}
// Close File
err = _close(file);
if(err==-1){
printf("Error closing file.\n");
exit(1);
}else{
printf("File closed.\n");
}
_ffree(data);
return 0;
}
.
.
文件输出
.
.
使用 data[256];
输出应该是这样的。总共 256 个字节。
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
使用data = _fmalloc(256);
不布埃诺!请注意,这还会产生一个额外的字节,总计 257 个字节。
00 00 38 14 00 01 05 00 00 00 00 00 00 00 E5 02 A2 01 01 00 1F 01 7E 2B 43 3A 5C 46 49 4C 45 2E 45 58 45 00 3C 00 50 41 54 48 3D 5A 3A 5C 00 43 4F 4D 53 50 45 43 3D 5A 3A 5C 43 4F 4D 4D 41 4E 44 2E 43 4F 4D 00 42 4C 41 53 54 45 52 3D 41 32 32 30 20 49 35 20 44 31 20 48 35 20 54 36 00 00 0D 0A 00 42 2B 4B 2B 62 2B 00 00 06 09 6A D4 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
文本视图
..8...........å.¢.....~+C:\FILE.EXE.<.PATH=Z:.COMSPEC=Z:\COMMAND.COM.BLASTER=A220 I5 D1 H5
T6.....B+K+b+....jÔ.................................................................................................................................................
malloc
情况,_write(file, &data, 256)
需要 _write(file, data, 256)
。它适用于自动分配的情况,因为 data
和 &data
是数组的相同地址(尽管类型不同)。
因此,我最终需要 _write() 和 _read() 函数的 _far 版本。编译器没有提供这些,所以我自己做了。如果这些看起来有点粗糙,请原谅我,但我以前从未做过这样的事情,所以这对我来说是一次很好的学习经历。这是我想出的代码。
int _fwrite(int fd, void __far *buffer, unsigned int length)
{
void *buffer_offset = 0; // used to pass the offset of buffer to _write()
unsigned int buffer_segment = 0; // used to change the value of the data segment register (DS)
unsigned long int buffer_copy = 0; // used for temporary, corruptible storage of buffer
int result = 0; // used for returning number of bytes written or an error from _write()
// store the full __far pointer buffer in buffer_copy as a 32 bit int so that we can use bitwise operators
buffer_copy = (unsigned long int)buffer;
// left shift the address stored in buffer_copy two bytes to get the offset address
buffer_offset = (void *)(buffer_copy << 16);
// right shift the address stored in buffer_copy two bytes to get the segment address
buffer_segment = buffer_copy >> 16;
// change the data segment register to the one that buffer points to so that _write() will work on far data
asm
{
push ds
mov ds,buffer_segment
}
// do the file write
result = _write(fd, buffer_offset, length);
// restore previous data segment register value so that near data can be accessed again
asm
{
pop ds
}
return result;
}
int _fread(int fd, void __far *buffer, unsigned int length)
{
void *buffer_offset = 0; // used to pass the offset of buffer to _read()
unsigned int buffer_segment = 0; // used to change the value of the data segment register (DS)
unsigned long int buffer_copy = 0; // used for temporary, corruptible storage of buffer
int result = 0; // used for returning number of bytes written or an error from _read()
// store the full __far pointer buffer in buffer_copy as a 32 bit int so that we can use bitwise operators
buffer_copy = (unsigned long int)buffer;
// left shift the address stored in buffer_copy two bytes to get the offset address
buffer_offset = (void *)(buffer_copy << 16);
// right shift the address stored in buffer_copy two bytes to get the segment address
buffer_segment = buffer_copy >> 16;
// change the data segment register to the one that buffer points to so that _read() will work on far data
asm
{
push ds
mov ds,buffer_segment
}
// do the file read
result = _read(fd, buffer_offset, length);
// restore previous data segment register value so that near data can be accessed again
asm
{
pop ds
}
return result;
}