Access violation writing location 0x00000000. memset function issues - c++

#include <iostream>
#include <string.h>
using namespace std;
void newBuffer(char* outBuffer, size_t sz) {
outBuffer = new char[sz];
}
int main(void) {
const char* abcd = "ABCD";
char* foo;
foo = NULL;
size_t len = strlen(abcd);
cout<<"Checkpoint 1"<<endl;
newBuffer(foo, len);
cout<<"Checkpoint 2"<<endl;
cout<<"Checkpoint 2-A"<<endl;
memset(foo, '-', len);
cout<<"Checkpoint 3"<<endl;
strncpy(foo, abcd, len);
cout<<"Checkpoint 4"<<endl;
cout << foo << endl;
int hold;
cin>>hold;
return 0;
}
This program crashes between checkpoint 2-1 and 3. What it tries to do is to set the char array foo to the char '-', but it fails because of some access issues. I do not understand why this happens. Thank you very much in advance!

Your newBuffer function should accept the first parameter by reference so that changes made to it inside the function are visible to the caller:
void newBuffer(char*& outBuffer, size_t sz) {
outBuffer = new char[sz];
}
As it is now, you assign the result of new char[sz] to the local variable outBuffer which is only a copy of the caller's foo variable, so when the function returns it's as if nothing ever happened (except you leaked memory).
Also you have a problem in that you are allocating the buffer to the size of the length of ABCD which is 4. That means you can hold up to 3 characters in that buffer because one is reserved for the NUL-terminator at the end. You need to add + 1 to the length somewhere (I would do it in the call to the function, not inside it, because newBuffer shouldn't be specialised for C-strings). strncpy only NUL-terminates the buffer if the source string is short enough, so in this case you are only lucky that there happens to be a 0 in memory after your buffer you allocated.
Also don't forget to delete[] foo in main after you're done with it (although it doesn't really matter for a program this size).

It fails because your newBuffer function doesn't actually work. The easiest way to fix it would be to change the declaration to void newBuffer (char *&outBuffer, size_t sz). As it's written, the address of the newly allocated memory doesn't actually get stored into main's foo because the pointer is passed by value.

You are passing the pointer by value. You would need to pass either a reference to the pointer, or the address of the pointer.
That said, using the return value would be better in my view:
char* newBuffer(size_t sz) {
return new char[sz];
}
When written this way, the newBuffer function doesn't really seem worthwhile. You don't need it. You can use new directly and that would be clearer.
Of course, if you are using C++ then this is all rather pointless. You should be using string, smart pointers etc. You should not have any need to call new directly. Once you fix the bug you are talking about in this question you will come across the problem that your string is not null-terminated and that the buffer is too short to hold the string since you forgot to allocate space for the null-terminator. One of the nice things about C++ is that you can escape the horrors of string handling in C.

Related

Char passing to other function best practice

I want to pass string to second function where it fills the character array and gives the value back. In the first function I want to take the string length after second function fills it.
first step
Planning to pass the character array
char data[10]="";
GetData(data); // Here Iam doing memset value to data
strlen(data);
second step
Planning to pass the character pointer
char *data;
GetData(data); // what I should do
strlen(data);
Can someone suggest which is the best practice
You want to use std::string, something like:
std::string data;
void GetData(std::string& str);
passing by non-const reference allows GetData to alter str.
Ideally the character pointer should be owned by the caller, and should take care of allocation (if possible, or callee has to do that on behalf of the caller) and deallocation
char *data = (char *) NULL; // should initialize to know allocated or not
the prototype of the call, GetData should be:
void GetData(char *& d); // pointer passed as reference
Within GetData, d shoud be allocated as:
d = new char[size]; //size should be appropriately decided including null terminating character
for example, if you wish to store a "hello" say, d should be allocated as :
d = new char[5+1]; // example
once done, in the caller, you must deallocate as:
if (data) delete [] data;
data = (char *) NULL;
The "classic", C-compatible method in Windows (where Visual C++ is most used) is to have a function that takes the buffer size as argument, and returns the size or length of data copied. Example:
//Inputs:
// buffer: [out/opt] If not null, write data here.
// size: [in] Buffer size including null terminator, ignored if buffer is null.
//Outputs:
// buffer: The data.
// Return Value: Length of data written to the buffer, without null terminator.
int GetData(char *buffer, size_t bufferSize);
This allows calling the function with a null buffer to obtain the length to allocate, allocate the data, and call the function again.
However, it's not very C++ and it's error-prone. Passing a pointer/reference to the pointer to allocate is better from a language standpoint, but has its drawbacks when crossing a DLL boundary, where it's recommended that any data allocated by a DLL be deallocated by the same DLL (preventing the use of ordinary smart pointers).

Memory leak when using smart pointers

Consider the following function:
unique_ptr<char> f(const wstring key, const unsigned int length)
{
assert(length <= key.length());
const wstring suffix = key.substr(length, key.length() - length);
const size_t outputSize = suffix.length() + 1; // +1 for null terminator
char * output = new char[outputSize];
size_t charsConverted = 0;
const wchar_t * outputWide = suffix.c_str();
wcstombs_s(&charsConverted, output, outputSize, outputWide, suffix.length());
return unique_ptr<char>(output);
}
The intent here is to accept a wstring, select length characters from the end, and return them as a C-style string that's wrapped in a unique_ptr (as required by another library - I certainly didn't chose that type :)).
One of my peers said in passing that he thinks this leaks memory, but he didn't have time to elaborate, and I don't see it. Can anybody spot it, and if so explain how I ought to fix it? I probably have my blinders on.
It's not necessarily a leak, but it is undefined behavior. You created the char array using new[] but the unique_ptr<char> will call delete, and not delete[] to free the memory. Use unique_ptr<char[]> instead.
Also, your conversion may not always behave the way you want it to. You should make 2 calls to wcstombs_s, in the first one pass nullptr as the second argument. This will return the number of characters required in the output string.
wcstombs_s(&charsConverted, nullptr, 0, outputWide, suffix.length());
Check the return value, and then use the result stored in charsConverted to allocate the output buffer.
auto output = std::unique_ptr<char[]>(new char[charsConverted]);
// now use output.get() to get access to the raw pointer

C++ Allocated Memory Problem

It has been a long time since I have programmed in C++, but I recently wrote a little C++ function and am having a little bit of trouble. The function returns a struct, Result, that have some strings in it. I thought I allocated memory for the strings, but jsonResult is sometimes partially overwritten.
//The structs
struct Interp {
int score;
char* sentence;
char* jsonResult;
};
struct Result {
int resultCode;
char* errorMessage;
Interp interp;
};
...
//Inside the function
Result result;
//Store decode
const char* jsonResult,* sentence;
if (result.resultCode == -1)
{
LVInterpretation interp = port.GetInterpretation(voiceChannel, 0);
result.interp.score = interp.Score();
sentence = interp.InputSentence();
jsonResult = interp.ResultData().Print(SI_FORMAT_ECMA);
}
//Allocate memory for strings
result.interp.jsonResult = new char[strlen(jsonResult) + 1];
strcpy(result.interp.jsonResult, jsonResult);
result.interp.sentence = new char[strlen(sentence) + 1];
strcpy(result.interp.sentence, sentence);
result.errorMessage = new char[strlen(errorMessage) + 1];
strcpy(result.errorMessage, errorMessage);
return result;
Other info:
I am observing all of this behind the python binding that I wrote, using ctypes. Don't think that is really effecting anything though.
Use std::string. You won't regret it.
I'd put money on your problem being in here:
jsonResult = interp.ResultData().Print(SI_FORMAT_ECMA);
Who 'owns' the char* array returned by Print()? Maybe it's attempting to return a pointer to memory that's out of scope???
example:
char* badFunction(void)
{
char test[100];
strcpy(test,"This is really clever"); // oh, yeah?
return test; // returns pointer to data that's out of scope
}
One other thing. Assign null pointers to sentence, jsonResult, etc when you declare them. Otherwise you could end up strcpy()ing uninitialized data,
Couple of things:
What does "partially overwritten" mean? How do you know this? i.e. what is your expected output vs. what you see?
It's not really clear how result.resultCode is set to -1 (or if it is at all), and if it is set, how does the memory get allocated in interp.InputSentence() and interp.ResultData().Print(SI_FORMAT_ECMA)? I'd suggest that your problem lies there
The rest of the code should work as long as jsonResult and sentence contain valid null terminated strings.

malloc pointer function passing fread

Can't figure out what's wrong, I don't seem to be getting anything from fread.
port.h
#pragma once
#ifndef _PORT_
#define _PORT_
#include <string>
#ifndef UNICODE
typedef char chr;
typedef string str;
#else
typedef wchar_t chr;
typedef std::wstring str;
inline void fopen(FILE ** ptrFile, const wchar_t * _Filename,const wchar_t * _Mode)
{
_wfopen_s(ptrFile,_Filename,_Mode);
}
#endif
#endif
inside main()
File * f = new File(fname,FileOpenMode::Read);
chr *buffer;
buffer = (wchar_t*)malloc(f->_length*2);
for(int i=0;i<f->_length;i++)
{
buffer[i] = 0;
}
f->Read_Whole_File(buffer);
f->Close();
for(int i=0;i<f->_length;i++)
{
printf("%S",buffer[i]);
}
free(buffer);
inside file class
void Read_Whole_File(chr *&buffer)
{
//buffer = (char*)malloc(_length);
if(buffer == NULL)
{
_IsError = true;
return;
}
fseek(_file_pointer, 0, SEEK_SET);
int a = sizeof(chr);
fread(&buffer,_length ,sizeof(chr) , _file_pointer);
}
You're mixing pointers and references all over the place.
Your function only needs to take a pointer to the buffer:
void Read_Whole_File(char *buffer) { ... }
And you should pass that pointer as-is to fread(), don't take the address of the pointer:
size_t amount_read = fread(buffer, _length, sizeof *buffer, _file_pointer);
Also remember:
If you have a pointer ptr to some type, you can use sizeof *ptr and remove the need to repeat the type name.
If you know the length of the file already, pass it to the function so you don't need to figure it out twice.
In C, don't cast the return value of malloc().
Check for errors when doing memory allocation and I/O, things can fail.
buffer is a reference to a chr *. Yet you're reading into &buffer which is a chr ** (whatever that is). Wrong.
You don't even need to pass a reference to buffer in Read_Whole_File, just use a regular pointer.
aside from your original problem...
from your code:
typedef char chr;
chr *buffer;
buffer = (wchar_t*)malloc(f->_length*2);
for(int i=0;i<f->_length;i++)
{
buffer[i] = 0;
}
don't you think there is something wrong here ? in case you cannot spot the errors, here is the list:
chr is a char, so buffer is a char *
you are using malloc. are you coding in C or in C++ ? if it is C++, consider using new
the buffer you allocate is explicitly casted to a wchar_t * but buffer is a char *
in the malloc you are allocating a block of size length*2 when you should be using length * sizeof(w_char_t). don't make any assumption on the size of a type (and even writing sizeof(char) is no problem, it renders the intentions explicit)
the for loop goes from 0 to length, but since buffer is defined as a buffer of char, only length bytes are initialized, whereas you alocated length*2 bytes, so half your buffer is still uninitialized.
memset() has been defined to avoid this kind of for loop...
please be a little bit careful when coding !
First a couple of nits:
What's with the malloc and free? What's wrong with new and delete? You are obviously writing C++ here, so write C++.
Overloading fopen, fseek, fread in the case of wchar_t bothers me, immensely. Much better: Use templates, or define your own functions. Don't overload those names that belong to C.
This is not not a nit. The following is almost certainly not doing what you want:
fread(&buffer,_length ,sizeof(chr) , _file_pointer);
chr here is a pointer to a reference, so sizeof is almost certainly going to be either 32 or 64.

Since I can't return a local variable, what's the best way to return a string from a C or C++ function?

As a follow-up to this question:
From what I've seen, this should work as expected:
void greet(){
char c[] = "Hello";
greetWith(c);
return;
}
but this will cause undefined behavior:
char *greet(){
char c[] = "Hello";
return c;
}
If I'm right, what's the best way to fix the second greet function? In an embedded environment? On a desktop?
You're absolutely right. Your c array in the second example is being allocated on the stack, and thus the memory will get reused immediately following. In particular, if you had code like
printf("%s\n",greet());
you'd get weird results, because the call to printf would have reused some of the space of your array.
The solution is to allocate the memory somewhere else. For expample:
char c[] = "Hello";
char * greet() {
return c;
}
Would work. Another choice would be to allocate it statically in scope:
char * greet() {
static char c[] = "Hello";
return c;
}
because static memory is allocated separately from the stack in data space.
Your third choice is to allocate it on the heap via malloc:
char * greet() {
char * c = (char *) malloc(strlen("Hello")+1); /* +1 for the null */
strcpy(c, "Hello");
return c;
}
but now you have to make sure that memory is freed somehow, or else you have a memory leak.
Update
One of those things that seems more confusing than I expect is what exactly a "memory leak" is. A leak is when you allocate memory dynamically, but lose the address so it can't be freed. None of these examples necessarily has a leak, but only the third one even potentially has a leak, because it's the only one that allocates memory dynamically. So, assuming the third implementation, you could write this code:
{
/* stuff happens */
printf("%s\n", greet());
}
This has a leak; the pointer to the malloc'ed memory is returned, the printf uses it, and then it's lost; you can't free it any longer. On the other hand,
{
char * cp ;
/* stuff happens */
cp = greet();
printf("%s\n", cp);
free(cp);
}
doesn't leak, because the pointer is saved in an auto variable cp long enough to call free() on it. Now, even though cp disappears as soon as execution passes he end brace, since free has been called, the memory is reclaimed and didn't leak.
If you are using C++, then you may want to consider using std::string to return strings from your second function:
std::string greet() {
char c[] = "Hello";
return std::string(c); // note the use of the constructor call is redundant here
}
Or, in a single threaded environment you can do:
char *greet() {
static char c[] = "Hello";
return c;
}
The static here allocates space in the global memory area, which never disappears. This static method is fraught with peril, though.
Depends if the embedded environment has a heap or not, if so, you should malloc as follows:
char* greet()
{
char* ret = malloc(6 * sizeof(char)); // technically " * sizeof(char)" isn't needed since it is 1 by definition
strcpy(ret,"hello");
return ret;
}
Note that you should later call free() to clean up. If you don't have access to dynamic allocation, you will need to make it a global, or a variable on the stack, but further up the call stack.
If you need to do this in C++, using std::string as suggested by Greg Hewgill is definitely the most simple and maintainable strategy.
If you are using C, you might consider returning a pointer to space that has been dynamically allocated with malloc() as suggested by Jesse Pepper; but another way that can avoid dynamic allocation is to have greet() take a char * parameter and write its output there:
void greet(char *buf, int size) {
char c[] = "Hello";
if (strlen(c) + 1 > size) {
printf("Buffer size too small!");
exit(1);
}
strcpy(buf, c);
}
The size parameter is there for safety's sake, to help prevent buffer overruns. If you knew exactly how long the string was going to be, it would not be necessary.
You can use either of these:
char const* getIt() {
return "hello";
}
char * getIt() {
static char thing[] = "hello";
return thing;
}
char * getIt() {
char str[] = "hello";
char * thing = new char[sizeof str];
std::strcpy(thing, str);
return thing;
}
shared_array<char> getIt() {
char str[] = "hello";
shared_array<char> thing(new char[sizeof str]);
std::strcpy(thing.get(), str);
return thing;
}
The first requires you to not write to the returned string, but also is the simplest you can get. The last uses shared_array which automatically can clean up memory if the reference to the memory is lost (the last shared_array to it goes out of scope). The last and second last must be used if you require a new string everytime you call the function.
Returning malloc'd memory from a function as suggested by several of the other responses is just asking for a memory leak. The caller would have to know you malloc'd it and then call free. If they happened to call delete on it, the results are undefined (although probably okay).
It would be better to force the caller to provide the memory for you and then copy your string into it. This way the caller is on notice that he/she needs to clean up.
From what I've read the safest option is to make the caller responsible for allocating memory to hold the string. You must also check if the buffer is large enough to hold your string:
char *greet(char *buf, int size) {
char *str = "Hello!"
if (strlen(str) + 1 > size) { // Remember the terminal null!
return NULL;
}
strcpy(buf, str);
return buf;
}
void do_greet() {
char buf[SIZE];
if (greet(buf, SIZE) == NULL) {
printf("Stupid C");
}
else {} // Greeted!
}
A ton of work for a simple task... but there's C for you :-)
Oops! Guess I was beaten by random_hacker...
Allocate the character array in the heap?
Whether you can use malloc or not depends on just what you mean by "embedded environment".