Digital Mars DOS _fmalloc not giving pointer to usable memory? - c

I'm using the Digital Mars C compiler to write a 16-bit DOS program, in the small memory model. This program needs to save a file to the hard disk, and it also needs to allocate 64,000 bytes in memory to temporarily store data in preparation to save it, along with some other data, to the hard disk. The problem is that it was saving gibberish to the file, when it shouldn't be. I made a separate small program so that I could separate my possibly bugged code from code that shouldn't have any problems. So far, I've been able to track the problem down to the _fmalloc() function in Digital Mars. When I write data that has been allocated with _fmalloc() the data gets corrupted with what seems like program data. When I allocate memory off of the stack, there is no problem and the program works as intended.
.
.
File Test Program
This is the small program I wrote to eliminate possible problems in my code and figure out where the problem is.
#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;
}
.
.
File Output
.
.
Using data[256];
This is what the output should look like. 256 bytes total.
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
01 01 01
Using data = _fmalloc(256);
NO BUENO! Note that this also produces an extra byte, for a grand total of 257 bytes.
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
text view
..8...........å.¢.....~+C:\FILE.EXE.<.PATH=Z:.COMSPEC=Z:\COMMAND.COM.BLASTER=A220
I5 D1 H5
T6.....B+K+b+....jÔ.................................................................................................................................................

_write(file, &data, 256) needs to be _write(file, data, 256) for the malloc case. It works for the auto allocated case because data and &data are the same address for arrays (though different types).

So, I ended up needing a _far version of the _write() and _read() functions. These were not provided with the compiler, so I made my own. Forgive me if these seem a little crude, but I've never done anything like this before, so this was a good learning experience for me. Here is the code I came up with.
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;
}

Related

C: Memory allocation issues

I'm having an issue with (I think) memory reallocation in C. The program is meant to run such that when fopen(array, &num); is called, it will first retrieve the number of elements in the array from file and place that in num, reallocate memory for the array pointer given to give it enough room to store the contents of the file proper, then copy the values over into that array. This seems to work while still in the fopen function (shown by 'mark 1'), but does not work outside of this (shown by 'mark 2') instead seeming to spew out random memory garbage. Any help appreciated (both with code and formatting my poorly laid out question).
//main.c
void Rtest(){
char num;
struct individual *array;
array = (struct individual *) malloc(sizeof(struct individual));
openf(array, &num);
printf("%d\n", num);
for (int i = 0; i < num; i++) {printf("%s\n", array[i].name);} //mark 2
free(array);
}
//fil.h
struct individual {
char name[32];
char stats[7];
char role;
char roles[13];
};
void openf(struct individual *array, char *num){
FILE *fp;
fp = fopen("save.bin", "rb");
fread(num, 1, sizeof(char), fp);
array = (struct individual *)realloc(array, *num * sizeof(struct individual));
printf("%d\n", sizeof(*array));
fread(array, *num, sizeof(struct individual), fp);
for (int i = 0; i < *num; i++) {printf("%s\n", array[i].name);} //mark 1
fclose(fp);
}
File contents:
03 43 61 72 6C 73 6F 6E 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 01 02 03 04 05 06 08 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 43 61 72 6C 73 6F 6E 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 01 02 03 04 05 06 08 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 43 61 72 6C 73 6F 6E 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 01 02 03 04 05 06 08 00 01 02 03 04 05 06 07 08 09 0A 0B 0C
When you want to change the argument inside a function, you pass a pointer to it.
For example, inside Rtest you declared a char called num. It has no value, and you sent it to openf, But you actually sent the pointer to num since you wanted to change its value, you did it correctly and indeed openf changed num value successfully.
But how about array? Well, you declared it on Rtest and allocated space in memory for it, which is all correct. Then, you wanted to send it to Rtest as a pointer so the function could change it.
array is a variable of the type "pointer to struct individual". This is okay, but if you wanted to change it inside Rtest, well you need to send a pointer for that variables.. hence, you needed a "POINTER TO pointer to struct individual". Note that the variable name was copied from before and I just added "POINTER TO"
I'm sure you know what pointer to pointer is, and what you needed to do is use:
openf(&array, &num);
And of course modift openf as well so it will use the new "pointer to pointer", something like that:
void openf(struct individual **array, char *num){
FILE *fp;
fp = fopen("save.bin", "rb");
fread(num, 1, sizeof(char), fp);
*array = (struct individual **)realloc(*array, *num * sizeof(struct individual));
printf("%d\n", sizeof(**array));
fread(*array, *num, sizeof(struct individual), fp);
for (int i = 0; i < *num; i++) {printf("%s\n", (*array)[i].name);} //mark 1
fclose(fp);
}
When I run this code on my machine, along with Rtest and provided save.bin I get the following output:
53
Carlson
Carlson
Carlson
3
Carlson
Carlson
Carlson
EDIT:
As #WhozCraig mentioned in the comments, You could use the unused return value for the function and return the pointer for the "new" array, which might be a slightly better way of doing things here instead of the "pointer to pointer" stuff, but its up to you.

Write() in a file, the words occur twice

I am current writing a file system, and init the disk. I am trying to write into the disk block.
int main(){
char name[] = "disk";
create_disk(name); // fd already define in global var;
open_disk(name);
write(fd,"one",16);
write(fd,"two",16);
write(fd,"three",16);
close(fd);
}
Here is the outcome in the file
IN HEX
Offset: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000: 6F 6E 65 00 74 77 6F 00 74 68 72 65 65 00 00 00 one.two.three...
00000010: 74 77 6F 00 74 68 72 65 65 00 00 00 00 14 00 00 two.three.......
00000020: 74 68 72 65 65 00 00 00 00 14 00 00 00 00 00 00 three...........
00000030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
My question: I only write "one", "two", "three" once each, why it giving me multiple copies of "three", "two".
How can I make my outcome looks like this?
one.............
two.............
three...........
................
................
You're writing 16 bytes from a much shorter string (i.e. reading memory you should not be). That's undefinable behavior.
Beware the nasal demons.
What you really want is something like this:
char buffer[16] = { 0 };
strcat(buffer, "one");
write(fd,buffer,16);
Now you are writing 16 chars out of a 16 char buffer which is perfectly ok.

Save audio stream in file using C libwebsockets

I have a C server that uses libwebsockets and I want to save a received audio stream in a file on disk.
Here is my code snippet:
#define FILENAME "/home/ubuntu/Desktop/file.wav"
FILE *received_file;
struct lws_context *Audiocontext;
static int callback_audio(
struct lws *wsi,
enum lws_callback_reasons reason,
void *user, void *in, size_t len)
{
switch (reason) {
case LWS_CALLBACK_ESTABLISHED:
{
printf("client is connected\n");
received_file = fopen(FILENAME, "w+");
if (received_file == NULL)
{
printf("Failed to open file\n");
exit(EXIT_FAILURE);
}
}
break;
case LWS_CALLBACK_RECEIVE: {
if(strcmp((char*)in,"EOS")==0)
{
printf("End of stream!\n");
fclose(received_file);
}
else
{
fwrite(in, 1, len, received_file);
}
}
}
}
I got the message "client is connected" and also the file, but the content isn't ok, I cannot play it. I think there is a problem regarding the way I save the stream on file using fwrite().
The client is sending audio chunks encoded as wav, 16Khz, mono. Here is a snippet from client (it's a javascript client, the full code is here:http://kaljurand.github.io/dictate.js/).
if (recorder) {
recorder.stop();
config.onEvent(MSG_STOP, 'Stopped recording');
// Push the remaining audio to the server
recorder.export16kMono(function(blob) {
socketSend(blob);
socketSend(TAG_END_OF_SENTENCE);
recorder.clear();
}, 'export16kMono');
config.onEndOfSpeech();
} else {
config.onError(ERR_AUDIO, "Recorder undefined");
}
The client is working well, I use it for exactly the same task, but using a Java server. I would appreciate if someone could indicate me how to save these audio chunks in a valid file.
I think that you do not write header in your wav file. To do so,
you can write some function to do so see specification here
or you can use a dedicaded library, like libsndfile, which is not so complicated to use:
// instead of fopen, write something like
SF_INFO info;
SNDFILE * sf;
info.samplerate = sample_rate;
info.channels = 1;
info.sections = 1;
info.seekable = 0;
info.frames = 0;
info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
sf = sf_open(filename, SFM_WRITE, &info);
// instead of fwrite, something like
sf_write_short(sf, in, len / sizeof(short));
// and instead of fclose
sf_close(sf);
I didn't use libsndfile, but I change something on the client side. This is the current hexdump output:
00000000 52 49 46 46 20 60 00 00 57 41 56 45 66 6d 74 20 |RIFF `..WAVEfmt |
00000010 10 00 00 00 01 00 02 00 44 ac 00 00 10 b1 02 00 |........D.......|
00000020 04 00 10 00 64 61 74 61 00 60 00 00 00 00 00 00 |....data.`......|
00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00006020 00 00 00 00 00 00 00 00 00 00 00 00 52 49 46 46 |............RIFF|
00006030 20 60 00 00 57 41 56 45 66 6d 74 20 10 00 00 00 | `..WAVEfmt ....|
00006040 01 00 02 00 44 ac 00 00 10 b1 02 00 04 00 10 00 |....D...........|
00006050 64 61 74 61 00 60 00 00 00 00 00 00 00 00 00 00 |data.`..........|
00006060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
0000c050 00 00 00 00 00 00 00 00 52 49 46 46 20 60 00 00 |........RIFF `..|
0000c060 57 41 56 45 66 6d 74 20 10 00 00 00 01 00 02 00 |WAVEfmt ........|
0000c070 44 ac 00 00 10 b1 02 00 04 00 10 00 64 61 74 61 |D...........data|
0000c080 00 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |.`..............|
0000c090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
It seems to be wav encoded, but i don't have a content.

How can I write a structure to a file ?

I have tried to look this up in multiple places and I cannot understand why fwrite doesn't work.
If I had a structure with 100 fields I would not want to use fprintf with 100 format specifiers.
struct emp
{
char name[15];
int age;
int salary;
char address[30];
};
int main()
{
char str[60];
struct emp emp1[5] = {{"Yoda",23,45000,"Asia"},{"Darth",34,2344,"NAmerica"},{"Jabba",22,5566,"Africa"},{"Luke",33,3399,"SAmerica"},{"Laya",44,6677,"Europe"}};
FILE *fp;
fp = fopen("C:/.../sampleText.txt","w");`
int i=0;
for(i=0; i<5; i++)
{
fwrite(&emp1[i],sizeof(emp1[i]),1,fp);
//fprintf(fp,"%s, %d, %d, %s\n",&emp1[i].name,emp1[i].age,emp1[i].salary,emp1[i].address);
}
fclose(fp);
getch();
}
There are two answers:
It does work, if everything is set correctly and porting the written data to other machines is not an issue.
It doesn't work if you have any of a large number of common features in data structures, or if you need to move the data from one type of machine (say an Intel machine) to another type (say PowerPC or SPARC).
In your example structure, you have no pointers, so you could write the structure verbatim to a file, and then in another invocation of the program running on the same (type of) machine, you could read it back in, and you would see the same data.
However, if your structure contained pointers, you could not meaningfully write the structure to disk. The pointers in one invocation of the program need not have any significance in another invocation of the program. If you needed to port the data between a little-endian (Intel) and big-endian (PowerPC, SPARC) machine, you'd have to use a platform-neutral way of accessing the data; simply writing the data to disk would not work.
So, where portability is not an issue, this code should work — Unix or Windows. It uses the "wb" and "rb" arguments to fopen() because the data is binary data, not plain text. The b is optional but harmless on Unix; it is crucial on Windows. The code also fixes the file name to sampledata.bin so it can be run on either platform, writing in the current directory. It writes the data; it then reads the data; it then compares the read data with the written data, reporting any problems. If the program says nothing, all is OK.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct emp
{
char name[15];
int age;
int salary;
char address[30];
};
int main(void)
{
char const filename[] = "sampledata.bin";
struct emp emp1[5] =
{
{ "Yoda", 23, 45000, "Asia" },
{ "Darth", 34, 2344, "N America" },
{ "Jabba", 22, 5566, "Africa" },
{ "Luke", 33, 3399, "S America" },
{ "Leia", 44, 6677, "Europe" },
};
struct emp emp2[5];
FILE *ifp;
FILE *ofp;
int i;
ofp = fopen(filename, "wb");
if (ofp != 0)
{
if (fwrite(emp1, sizeof(emp1), 1, ofp) != 1)
{
fprintf(stderr, "Failed to write to %s\n", filename);
exit(1);
}
fclose(ofp);
}
ifp = fopen(filename, "rb");
if (ifp != 0)
{
if (fread(emp2, sizeof(emp2), 1, ifp) != 1)
{
fprintf(stderr, "Failed to read from %s\n", filename);
exit(1);
}
fclose(ifp);
}
for (i = 0; i < 5; i++)
{
if (emp1[i].age != emp2[i].age ||
emp1[i].salary != emp2[i].salary ||
strcmp(emp1[i].name, emp2[i].name) != 0 ||
strcmp(emp1[i].address, emp2[i].address) != 0)
printf("Difference in record %d\n", i);
}
return 0;
}
Content of the file sampledata.bin:
0x0000: 59 6F 64 61 00 00 00 00 00 00 00 00 00 00 00 00 Yoda............
0x0010: 17 00 00 00 C8 AF 00 00 41 73 69 61 00 00 00 00 ........Asia....
0x0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x0030: 00 00 00 00 00 00 00 00 44 61 72 74 68 00 00 00 ........Darth...
0x0040: 00 00 00 00 00 00 00 00 22 00 00 00 28 09 00 00 ........"...(...
0x0050: 4E 20 41 6D 65 72 69 63 61 00 00 00 00 00 00 00 N America.......
0x0060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x0070: 4A 61 62 62 61 00 00 00 00 00 00 00 00 00 00 00 Jabba...........
0x0080: 16 00 00 00 BE 15 00 00 41 66 72 69 63 61 00 00 ........Africa..
0x0090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x00A0: 00 00 00 00 00 00 00 00 4C 75 6B 65 00 00 00 00 ........Luke....
0x00B0: 00 00 00 00 00 00 00 00 21 00 00 00 47 0D 00 00 ........!...G...
0x00C0: 53 20 41 6D 65 72 69 63 61 00 00 00 00 00 00 00 S America.......
0x00D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x00E0: 4C 65 69 61 00 00 00 00 00 00 00 00 00 00 00 00 Leia............
0x00F0: 2C 00 00 00 15 1A 00 00 45 75 72 6F 70 65 00 00 ,.......Europe..
0x0100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x0110: 00 00 00 00 00 00 00 00 ........
0x0118:
You don't specify what you mean by fwrite doesn't work, but I'll assume you're working on Windows, in which case you need to specify "wb" to fopen. By default on Windows, it's writing in text mode (i.e. "wt").
not a good idea to write struct to file or sockets as it is. It is inviting complex to solve problems. the best approach is to use serialization before writing. Also, as Jim pointed out above, make sure to open the file in binary.
Take a look in this question and the answers. there is a pretty good answer and explanation for your question.
Passing a structure through Sockets in C
Data serialization is a non-trivial task. As some others have pointed out, it is possible in some cases to write the contents of your struct to disk as binary data. It's the simplest to write, but it is unlikely to be stable. Each time you recompile your code, it can potentially change the format the data is written and read in.
Your best option is to use a standard data interchange format, such as CSV, XML, or JSON. There are many existing tools to utilize these formats, so you should look into using one of them.

strcat giving unexpected result

This is a very small portion of a large project...
These are typedefs defined in standard header file for the project.
typedef uint16_t u_int16_t;
typedef uint32_t u_int32_t;
typedef uint8_t u_int8_t;
Now this is the actual function causing problem ...
void function(u_int8_t *data1, u_int32_t data1len,
u_int8_t *data2, u_int32_t data2len)
{
FILE *fq,*fr,*fs;
char *data3;
int data3len;
data3len=data1len+data2len;
printf("\n%d",data1len);
printf("\n%d",data2len);
printf("\n%d",data3len);
fq=fopen("data1.txt","wb");
fwrite((char *)data1,data1len,1,fq);
fr=fopen("data2.txt","wb");
fwrite((char *)data2,data2len,1,fr);
data3=(char *)data1;
strcat(data3,(char *)data2);
fs=fopen("data3.txt","wb");
fwrite((char *)data3,data3len,1,fs);
}
Some output Snapshots ...
40
14
54
udit#udit-Dabba ~$ hexdump -C data1.txt
00000000 60 00 00 00 00 8c 06 00 00 00 00 00 00 00 00 00 |`...............|
00000010 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 |................|
00000020 00 00 00 00 00 00 00 02 |........|
00000028
udit#udit-Dabba ~$ hexdump -C data2.txt
00000000 00 26 00 26 00 00 00 01 00 00 00 02 34 12 00 65 |.&.&........4..e|
00000010 00 34 00 00 61 62 63 64 |.4..abcd|
00000018
udit#udit-Dabba ~$ hexdump -C data3.txt
00000000 60 00 00 00 00 8c 06 00 00 00 00 00 00 00 00 00 |`...............|
00000010 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 |................|
00000020 00 00 00 00 00 00 00 02 00 78 f8 65 00 00 00 02 |.........x.e....|
00000030 f4 1f 96 00 18 34 a6 bf 1c 03 96 00 88 f1 90 08 |.....4..........|
00000040
Why contents of data2.txt are not copied to data3.txt ??? If there is any other possible way then please tell me !!!! Thanx in advance ...
Why contents of data2.txt are not copied to data3.txt?
strcat is specifically for concatenating C strings and only copies up until the null terminator character. So it stops copying from the source once it encounters 00 which it considers the end of the string. Notice how data2 begins with a 00, so it stops immediately.
You'll instead need to memcpy with the destination being 1 past the last byte in data3 and the source being data2. You'll also need to fail gracefully if data3 (which is really data1) does not have enough space to hold data2.
I think you could do it much easier, saving you from ensuring that the respective memory block is large enough.
void function(u_int8_t *data1, u_int32_t data1len,
u_int8_t *data2, u_int32_t data2len)
{
FILE *fq,*fr,*fs;
char *data3;
fq=fopen("data1.txt","wb");
fwrite((char *)data1, data1len, 1, fq);
fclose(fq);
fr=fopen("data2.txt","wb");
fwrite((char *)data2, data2len, 1, fr);
fclose(fr);
fs=fopen("data3.txt","wb");
fwrite((char *)data1, data1len, 1, fs);
fwrite((char *)data2, data2len, 1, fs);
fclose(fs);
}
You try to append data2 to the end of data1.
You intend to put the result into a third string (data3), but in fact data3 is just data1; they point to the same location.
Your code is equivalent to
strcat (data1, data2);
which of course writes beyond data1's end.
(there is another problem: if the caller of the function uses a "string_literal" as argument#1,
data1 will not be writable. )
You probably have to allocate some memory for the resulting string and make point data3 to it.

Resources