i'm having a weird problem with allocating memory in c++
i'm creating a buffer and read file content into it.
problem is the allocating is incorrect and at the end of the printing there are weird chars...
the content of the file is "Hello"...
i'm sitting on it for hours... what can be the problem ? :(
void main()
{
FILE *fp;
char *buffer;
long file_size;
size_t result;
fp = fopen("input.txt","r");
if (fp == NULL) { fputs("File Error",stderr); exit(1); }
//get file size
fseek(fp, 0, SEEK_END);
file_size = ftell(fp);
rewind(fp);
//allocate memory to contain the whole file size
buffer = new char[file_size];
if (buffer == NULL) { fputs("Cannot allocate memory space",stderr); exit(2); }
//copy the file into the buffer
result = fread(buffer, 1, file_size, fp);
if (result != file_size) { fputs("Reading error",stderr); exit(3); }
cout<<buffer;
fclose(fp);
delete buffer;
}
You are not zero-terminating your buffer, so it's not a valid C/C++ string.
Try the following changes:
//allocate memory to contain the whole file size, plus one char for termination
buffer = new char[file_size + 1];
if (buffer == NULL) { fputs("Cannot allocate memory space",stderr); exit(2); }
//copy the file into the buffer
result = fread(buffer, 1, file_size, fp);
if (result != file_size) { fputs("Reading error",stderr); exit(3); }
// terminate buffer, so it becomes a valid string we can print
buffer[file_size] = '\0';
cout<<buffer;
Allocate one more place for termination character. And put it at the end of your buffer.
This will probably solve your problem.
buffer = new char[file_size + 1];
buffer[file_size] ='\0';
buffer must contain a NULL terminated string for your cout<<buffer output to make sense.
When you are in C++, what speaks against using C++?
see: http://www.cplusplus.com/doc/tutorial/files/
edit2: in response to Neil (the initial version printed an empty line 0):
int main () {
std::ifstream i ("main.cpp");
std::string str;
for (int line=0; getline (i, str); ++line) {
std::cout << line << ':' << str << '\n';
}
}
Related
So, I'm a relative newbie to network programming and programming in general, and I'm attempting to write a simple client/server text file transfer service. My code asks for the user to choose an upload or download option. When the user selects upload, the new file is created on the server's end, but isn't written with the data until the socket is closed. Also the string "upload" is appended onto the end of the text in the file.
I can't seem to find where my errors are, so any help would be greatly appreciated!
server.cpp
#define SIZE 1024
void write_file(int sockfd) // writing data to file function
{
int n;
FILE *fp;
char const *filename = "recv.txt";
char buffer[SIZE];
fp = fopen(filename, "w");
while (1)
{
n = recv(sockfd, buffer, SIZE, 0);
if (n <= 0)
{
break;
}
fprintf(fp, "%s", buffer);
bzero(buffer, SIZE);
}
fclose(fp);
return;
}
// in main
char msgRecv[10];
int n = 10;
while (n > 0)
{
rcv = read(connected_sd, &msgRecv, 10);
n -= rcv;
}
char msgUpload[10] = "upload";
if(strcmp(msgUpload, msgRecv) == 0)
{
write_file(connected_sd);
}
client.cpp
void send_file(FILE *points, int sockfd) // sending file through socket function
{
char bytes[SIZE] = {0};
bzero(bytes, SIZE);
while(fgets(bytes, SIZE, points) != NULL)
{
if(send(sockfd, bytes, sizeof(bytes), 0) == -1)
{
perror("Error in sending file.");
exit(1);
}
bzero(bytes, SIZE);
}
}
// in main
char msgUpload[10] = "upload";
send(sd, msgUpload, sizeof(msgUpload), 0);
string fileN;
cout << "What is the name of the file you wish to upload?\n";
cin >> fileN;
bzero(msgUpload, sizeof(msgUpload));
FILE *file;
char const *filename = fileN.c_str();
file = fopen(filename, "r");
if (file == NULL)
{
perror("Error in reading file.\n");
exit(1);
}
send_file(file, sd);
printf("File data sent successfully.\n\n");
fclose(file);
the program is to read back multiple bin files
there is an above-mentioned error happened at the end of "main" program. where did I code wrong? thank you for help
char* read_back(const char* filename)
{
FILE* pFile;
long lSize;
char* buffer;
pFile = fopen(filename, "rb");
if (pFile == NULL) { fputs("File error", stderr); exit(1); }
fseek(pFile, 0, SEEK_END);
lSize = ftell(pFile);
rewind(pFile); // set file pos at the begining
// copy the file into the buffer:
buffer = (char*)malloc(sizeof(char)*lSize);
size_t result = fread(buffer, 1, lSize, pFile);
if (result != lSize) { fputs("Reading error", stderr); exit(3); }
fclose(pFile);
return buffer;
}
int main() {
const char *fname[2] ;
fname[0] = "C:\\0_data.bin";
fname[1] = "C:\\1_data.bin";
fname[2] = "C:\\2_data.bin";
int i;
char * readback_data;
for (i = 0; i < 3; ++i)
{
readback_data=read_back(fname[i]);
}
return 0;
}
const char *fname[2] ;
This declares an array with two values, two pointers: fname[0] and fname[1].
fname[0] = "C:\\0_data.bin";
fname[1] = "C:\\1_data.bin";
fname[2] = "C:\\2_data.bin";
This attempts to put three pointers into an array that's sized only for two. That's your stack corruption, right here.
I composed below code to readback binary files by VC2017. In debug mode, I like to see the values in "buffer". but I could not see readable values.
my questions are:
how can I view the readable result?
I did "sizeof(buffer)", it returned 4, which was less than what I expected. I expected the buffer to be same size and the file size. why?
Thank you very much for enlightening me.
char* read_back(const char* filename)
{
FILE* pFile;
long lSize;
char* buffer;
pFile = fopen(filename, "rb");
if (pFile == NULL)
{
fputs("File error", stderr);
exit(1);
}
fseek(pFile, 0, SEEK_END);
lSize = ftell(pFile);
rewind(pFile); // set file pos at the begining
// copy the file into the buffer:
buffer = (char*)malloc(sizeof(char)*lSize);
size_t result = fread(buffer, 1, lSize, pFile);
if (result != lSize)
{
fputs("Reading error", stderr);
exit(3);
}
fclose(pFile);
return buffer;
}
Here's how to do your code in C++ (not the C code that you actually have)
#include <fstream>
#include <sstream>
#include <string>
std::string read_back(const char* filename)
{
std::ifstream file(filename, std::ios_base::binary);
std::ostringstream buffer;
buffer << file.rdbuf();
return buffer.str();
}
It returns a std::string not a char* but that's a good thing, because you don't have the issue of remembering to have to free the allocated memory.
As has been explained you misunderstand how pointers and sizeof work. Avoid pointers, they're hard.
I have a simple implementation of AES (CTR Mode, which allows encrypting/decrypting more than 16bytes)
And I want to read a file to a char array and then to encrypt it.
I have tried the following, without success:
long GetFileSize(const char* filePath)
{
FILE* pFile = fopen(filePath, "rb");
if (pFile == NULL)
{
printf("error");
getchar();
}
fseek(pFile, 0, SEEK_END);
long lSize = ftell(pFile);
rewind(pFile);
fclose(pFile);
return lSize;
}
// Reads given file to buffer, and returns pointer to that buffer.
// Caller should free this memory later.
unsigned char * ReadFile(const char * filePath)
{
FILE * pFile;
long lSize;
unsigned char * buffer;
size_t result;
pFile = fopen(filePath, "rb");
if (pFile == NULL) { fputs("File error", stderr); ; }
// obtain file size:
fseek(pFile, 0, SEEK_END);
lSize = ftell(pFile);
rewind(pFile);
// allocate memory to contain the whole file:
buffer = (unsigned char*)malloc(sizeof(unsigned char)*lSize);
if (buffer == NULL) { fputs("Memory error", stderr); ; }
// copy the file into the buffer:
result = fread(buffer, 1, lSize, pFile);
if (result != lSize) { fputs("Reading error", stderr); ; }
// terminate
fclose(pFile);
// the whole file is now loaded in the memory buffer. Return pointer to data.
return buffer;
}
int main(int argc, char *argv[])
{
//All char arrays are null terminated here...
uchar szkey[KEY_128] = "very strong key";
const char *filePath = "key.txt";
// Get file size which must be encrypted
long originalSize = GetFileSize(filePath);
// Make this size multiple of block size (16 bytes).
long multipleSize = (originalSize / 16 + 1) * 16;
// Store number of bytes that were needed for padding.
int nrOfPaddingBytes = (int)(multipleSize - originalSize);
// Now, read the file.
unsigned char * fileContents = ReadFile(filePath);
// Create a large buffer to store file contents (including padding bytes),
// and copy file contents to it.
unsigned char * buffer = (unsigned char*)malloc(multipleSize);
memcpy(buffer, fileContents, originalSize);
// Allocate space for ciphertext also (should also have size multiple of 8).
unsigned char * ciphertext = (unsigned char*)malloc(multipleSize);
char* cipherhex = (char*)malloc(multipleSize * 2);
char* decryptedhex = (char*)malloc(multipleSize);
unsigned char* dechex = (unsigned char*)malloc(multipleSize);
// Delete old file buffer.
free(fileContents);
fileContents = NULL;
// Pad the plaintext
for (int i = 0; i < nrOfPaddingBytes; i++)
{
buffer[originalSize + i] = nrOfPaddingBytes;
}
aes_ctx_t *ctx;
u64 nonce;
virtualAES::initialize();
ctx = virtualAES::allocatectx(szkey, sizeof(szkey));
virtualAES::rand_nonce(&nonce);
//encrypt
virtualAES::encrypt_ctr(ctx, buffer, ciphertext, sizeof(buffer), nonce);
cout << "cipherdata in ansi:\n" << ciphertext << "\n\n";
virtualAES::strtohex(ciphertext, cipherhex, originalSize);
cout << "cipherdata in hex:\n" << cipherhex << "\n\n";
return 0;
}
but it fails for some reason. Could someone provide me an algorithm to read a file for encrypting?
I'm having problems with byte array of chars.
I'm creating file transfer program, which transfers binary data over TCP socket.
So, when I'm getting data from chunks, I'm saving them to temporary container and then I have to add somewhere to hold whole data. I have tried std::vector but doesn't work well (or I'm using it wrong.)
size_t nbytes = 0;
char buffer[5]; //temporary container.
int result = 0;
std::vector<char> abc;
if (ioctl(sockfd, FIONREAD, (char*)&nbytes) < 0)
{
printf("[-] Error getting available data.\n");
return -1;
}
printf("[*] Bytes available: %lu\n", nbytes);
while(true)
{
if(nbytes > sizeof(buffer))
{
result = recv(sockfd, buffer, sizeof(buffer), 0);
for(int i = 0; i < result; i++)
{
abc.push_back(buffer[i]); //big data causes memory corruption.
}
nbytes -= result;
continue;
}
else if(nbytes <= sizeof(buffer) && nbytes != 0)
{
result = recv(sockfd, buffer, nbytes, 0);
for(int i = 0; i < result; i++)
{
abc.push_back(buffer[i]); //big data causes memory corruption.
}
break;
}
else
{
result = 0;
break;
}
}
printf("Data Received: %s", &abc[0]);
if recv fails it returns SOCKET_ERROR but you don't check it and instead use it as number of the bytes received. As SOCKET_ERROR is #defined to -1 you effectively read from address before buffer.
EDIT:
it turns out that original answer was wrong as in that case the loop would not execute at all.
However, the problem is that content of the vector is not null-terminated (as it is a plain buffer without any string semantics), so it looks like garbage, but it is actually OK.