Determine the nature of parameter in runtime - c++

I have a function
void fname(char* Ptr)
{
...
}
I want to know inside this function whether this pointer Ptr holds the address of dynamically allocated memory using new char[] or the address of locally allocated memory in the calling function. Is there any way I can determine that? I think <typeinfo> doesn't help here.

One way to do this is to have your own operator new functions and keep track of everything allocated so that you can just ask your allocation library if the address given is one it allocated. The custom allocator then just calls the standard one to actually do the allocation.
Another approach (messy and details highly OS dependent) may be to examine the process layout in virtual memory and hence determine which addresses refer to which areas of memory.
You can combine these ideas by actually managing your own memory pools. So if you get a single large chunk of system memory with known address bounds and use that for all new'd memory, you can just check that an address in is the given range to answer your question.
However: Any of these ideas is a lot of work and not appropriate if this problem is the only purpose in doing so.
Having said all that, if you do want to implement something, you will need to work carefully through all the ways that an address might be generated.
For example (and surely I've missed some):
Stack
Return from new
Inside something returned from new.
Was returned from new but already deleted (hopefully not, but that's why we need diagnostics)
statically allocated
static constant memory
command line arguments/ environment
code addresses.
Now, ignoring all that for a moment, and assuming this is for some debug purpose rather than system design, you might be able to try this kind of thing:
This is ugly, unreliable, not guaranteed by the standard, etc etc, but might work . . .
char* firstStack = 0;
bool isOnStack(const void* p)
{
char* check =(char*)p;
char * here = (char*)&check;
int a = firstStack - check;
int b = check - here;
return (a*b > 0);
}
void g(const char* p)
{
bool onStack = isOnStack(p);
std::cout << p << (onStack ? "" : " not" ) << " on stack " << std::endl;
}
void f()
{
char stuff[1024] = "Hello";
g(stuff);
}
void h()
{
char* nonsense = new char[1024];
strcpy(nonsense, "World");
g(nonsense);
delete [] nonsense;
}
int main()
{
int var = 0;
firstStack = (char*)&var;
f();
h();
}
Output:
Hello on stack
World not on stack

The short answer: no, you can't. You have no way of knowing whether Ptr is a pointer to a single char, the start of a statically allocated array, a pointer to a single dynamically allocated char, or the start of an array thereof.
If you really wanted to, you try an overload like so:
template <std::size_t N>
void fname(char Ptr[N])
{
// ...
}
which would match when passed a statically allocated array, whereas the first version would be picked when dealing with dynamically allocated memory or a pointer to a single char.
(But note that function overloading rules are a bit complicated in the presence of templates -- in particular, a non-template function is preferred if it matches. So you might need to make the original function take a "dummy" template parameter if you go for this approach.)

In vc++ there is an assertion _CrtIsMemoryBlock (http://msdn.microsoft.com/en-us/library/ww5t02fa.aspx#BKMK_CRT_assertions) that can be used to check if a pointer was allocated from the heap. This will only work when a debug heap is being used but this is fine if you are just wanting to add some 'debug only' assertions. This method has worked well for me in the past under Windows.
For Linux however I know of no such equivalent.
Alternatively you could use an inline assembler block to try to determine the if it is a stack address or not. This would be hardware dependent as it would rely heavily not only on the processor type but also on the memory model being used (flat address model vs segmented etc). Its probably best to avoid this type of approach.

Related

How to check that the address pointed by a pointer is pointing to an object not a garbage before reading or writing to this object? [duplicate]

Is there any way to determine (programatically, of course) if a given pointer is "valid"? Checking for NULL is easy, but what about things like 0x00001234? When trying to dereference this kind of pointer an exception/crash occurs.
A cross-platform method is preferred, but platform-specific (for Windows and Linux) is also ok.
Update for clarification:
The problem is not with stale/freed/uninitialized pointers; instead, I'm implementing an API that takes pointers from the caller (like a pointer to a string, a file handle, etc.). The caller can send (in purpose or by mistake) an invalid value as the pointer. How do I prevent a crash?
Update for clarification: The problem is not with stale, freed or uninitialized pointers; instead, I'm implementing an API that takes pointers from the caller (like a pointer to a string, a file handle, etc.). The caller can send (in purpose or by mistake) an invalid value as the pointer. How do I prevent a crash?
You can't make that check. There is simply no way you can check whether a pointer is "valid". You have to trust that when people use a function that takes a pointer, those people know what they are doing. If they pass you 0x4211 as a pointer value, then you have to trust it points to address 0x4211. And if they "accidentally" hit an object, then even if you would use some scary operation system function (IsValidPtr or whatever), you would still slip into a bug and not fail fast.
Start using null pointers for signaling this kind of thing and tell the user of your library that they should not use pointers if they tend to accidentally pass invalid pointers, seriously :)
Here are three easy ways for a C program under Linux to get introspective about the status of the memory in which it is running, and why the question has appropriate sophisticated answers in some contexts.
After calling getpagesize() and rounding the pointer to a page
boundary, you can call mincore() to find out if a page is valid and
if it happens to be part of the process working set. Note that this requires
some kernel resources, so you should benchmark it and determine if
calling this function is really appropriate in your api. If your api
is going to be handling interrupts, or reading from serial ports
into memory, it is appropriate to call this to avoid unpredictable
behaviors.
After calling stat() to determine if there is a /proc/self directory available, you can fopen and read through /proc/self/maps
to find information about the region in which a pointer resides.
Study the man page for proc, the process information pseudo-file
system. Obviously this is relatively expensive, but you might be
able to get away with caching the result of the parse into an array
you can efficiently lookup using a binary search. Also consider the
/proc/self/smaps. If your api is for high-performance computing then
the program will want to know about the /proc/self/numa which is
documented under the man page for numa, the non-uniform memory
architecture.
The get_mempolicy(MPOL_F_ADDR) call is appropriate for high performance computing api work where there are multiple threads of
execution and you are managing your work to have affinity for non-uniform memory
as it relates to the cpu cores and socket resources. Such an api
will of course also tell you if a pointer is valid.
Under Microsoft Windows there is the function QueryWorkingSetEx that is documented under the Process Status API (also in the NUMA API).
As a corollary to sophisticated NUMA API programming this function will also let you do simple "testing pointers for validity (C/C++)" work, as such it is unlikely to be deprecated for at least 15 years.
Preventing a crash caused by the caller sending in an invalid pointer is a good way to make silent bugs that are hard to find.
Isn't it better for the programmer using your API to get a clear message that his code is bogus by crashing it rather than hiding it?
On Win32/64 there is a way to do this. Attempt to read the pointer and catch the resulting SEH exeception that will be thrown on failure. If it doesn't throw, then it's a valid pointer.
The problem with this method though is that it just returns whether or not you can read data from the pointer. It makes no guarantee about type safety or any number of other invariants. In general this method is good for little else other than to say "yes, I can read that particular place in memory at a time that has now passed".
In short, Don't do this ;)
Raymond Chen has a blog post on this subject: http://blogs.msdn.com/oldnewthing/archive/2007/06/25/3507294.aspx
AFAIK there is no way. You should try to avoid this situation by always setting pointers to NULL after freeing memory.
On Unix you should be able to utilize a kernel syscall that does pointer checking and returns EFAULT, such as:
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <stdbool.h>
bool isPointerBad( void * p )
{
int fh = open( p, 0, 0 );
int e = errno;
if ( -1 == fh && e == EFAULT )
{
printf( "bad pointer: %p\n", p );
return true;
}
else if ( fh != -1 )
{
close( fh );
}
printf( "good pointer: %p\n", p );
return false;
}
int main()
{
int good = 4;
isPointerBad( (void *)3 );
isPointerBad( &good );
isPointerBad( "/tmp/blah" );
return 0;
}
returning:
bad pointer: 0x3
good pointer: 0x7fff375fd49c
good pointer: 0x400793
There's probably a better syscall to use than open() [perhaps access], since there's a chance that this could lead to actual file creation codepath, and a subsequent close requirement.
Regarding the answer a bit up in this thread:
IsBadReadPtr(), IsBadWritePtr(), IsBadCodePtr(), IsBadStringPtr() for Windows.
My advice is to stay away from them, someone has already posted this one:
http://blogs.msdn.com/oldnewthing/archive/2007/06/25/3507294.aspx
Another post on the same topic and by the same author (I think) is this one:
http://blogs.msdn.com/oldnewthing/archive/2006/09/27/773741.aspx ("IsBadXxxPtr should really be called CrashProgramRandomly").
If the users of your API sends in bad data, let it crash. If the problem is that the data passed isn't used until later (and that makes it harder to find the cause), add a debug mode where the strings etc. are logged at entry. If they are bad it will be obvious (and probably crash). If it is happening way to often, it might be worth moving your API out of process and let them crash the API process instead of the main process.
Firstly, I don't see any point in trying to protect yourself from the caller deliberately trying to cause a crash. They could easily do this by trying to access through an invalid pointer themselves. There are many other ways - they could just overwrite your memory or the stack. If you need to protect against this sort of thing then you need to be running in a separate process using sockets or some other IPC for communication.
We write quite a lot of software that allows partners/customers/users to extend functionality. Inevitably any bug gets reported to us first so it is useful to be able to easily show that the problem is in the plug-in code. Additionally there are security concerns and some users are more trusted than others.
We use a number of different methods depending on performance/throughput requirements and trustworthyness. From most preferred:
separate processes using sockets (often passing data as text).
separate processes using shared memory (if large amounts of data to pass).
same process separate threads via message queue (if frequent short messages).
same process separate threads all passed data allocated from a memory pool.
same process via direct procedure call - all passed data allocated from a memory pool.
We try never to resort to what you are trying to do when dealing with third party software - especially when we are given the plug-ins/library as binary rather than source code.
Use of a memory pool is quite easy in most circumstances and needn't be inefficient. If YOU allocate the data in the first place then it is trivial to check the pointers against the values you allocated. You could also store the length allocated and add "magic" values before and after the data to check for valid data type and data overruns.
I've got a lot of sympathy with your question, as I'm in an almost identical position myself. I appreciate what a lot of the replies are saying, and they are correct - the routine supplying the pointer should be providing a valid pointer. In my case, it is almost inconceivable that they could have corrupted the pointer - but if they had managed, it would be MY software that crashes, and ME that would get the blame :-(
My requirement isn't that I continue after a segmentation fault - that would be dangerous - I just want to report what happened to the customer before terminating so that they can fix their code rather than blaming me!
This is how I've found to do it (on Windows): http://www.cplusplus.com/reference/clibrary/csignal/signal/
To give a synopsis:
#include <signal.h>
using namespace std;
void terminate(int param)
/// Function executed if a segmentation fault is encountered during the cast to an instance.
{
cerr << "\nThe function received a corrupted reference - please check the user-supplied dll.\n";
cerr << "Terminating program...\n";
exit(1);
}
...
void MyFunction()
{
void (*previous_sigsegv_function)(int);
previous_sigsegv_function = signal(SIGSEGV, terminate);
<-- insert risky stuff here -->
signal(SIGSEGV, previous_sigsegv_function);
}
Now this appears to behave as I would hope (it prints the error message, then terminates the program) - but if someone can spot a flaw, please let me know!
There are no provisions in C++ to test for the validity of a pointer as a general case. One can obviously assume that NULL (0x00000000) is bad, and various compilers and libraries like to use "special values" here and there to make debugging easier (For example, if I ever see a pointer show up as 0xCECECECE in visual studio I know I did something wrong) but the truth is that since a pointer is just an index into memory it's near impossible to tell just by looking at the pointer if it's the "right" index.
There are various tricks that you can do with dynamic_cast and RTTI such to ensure that the object pointed to is of the type that you want, but they all require that you are pointing to something valid in the first place.
If you want to ensure that you program can detect "invalid" pointers then my advice is this: Set every pointer you declare either to NULL or a valid address immediately upon creation and set it to NULL immediately after freeing the memory that it points to. If you are diligent about this practice, then checking for NULL is all you ever need.
Setting the pointer to NULL before and after using is a good technique. This is easy to do in C++ if you manage pointers within a class for example (a string):
class SomeClass
{
public:
SomeClass();
~SomeClass();
void SetText( const char *text);
char *GetText() const { return MyText; }
void Clear();
private:
char * MyText;
};
SomeClass::SomeClass()
{
MyText = NULL;
}
SomeClass::~SomeClass()
{
Clear();
}
void SomeClass::Clear()
{
if (MyText)
free( MyText);
MyText = NULL;
}
void SomeClass::Settext( const char *text)
{
Clear();
MyText = malloc( strlen(text));
if (MyText)
strcpy( MyText, text);
}
Indeed, something could be done under specific occasion: for example if you want to check whether a string pointer string is valid, using write(fd, buf, szie) syscall can help you do the magic: let fd be a file descriptor of temporary file you create for test, and buf pointing to the string you are tesing, if the pointer is invalid write() would return -1 and errno set to EFAULT which indicating that buf is outside your accessible address space.
Peeter Joos answer is pretty good. Here is an "official" way to do it:
#include <sys/mman.h>
#include <stdbool.h>
#include <unistd.h>
bool is_pointer_valid(void *p) {
/* get the page size */
size_t page_size = sysconf(_SC_PAGESIZE);
/* find the address of the page that contains p */
void *base = (void *)((((size_t)p) / page_size) * page_size);
/* call msync, if it returns non-zero, return false */
int ret = msync(base, page_size, MS_ASYNC) != -1;
return ret ? ret : errno != ENOMEM;
}
There isn't any portable way of doing this, and doing it for specific platforms can be anywhere between hard and impossible. In any case, you should never write code that depends on such a check - don't let the pointers take on invalid values in the first place.
As others have said, you can't reliably detect an invalid pointer. Consider some of the forms an invalid pointer might take:
You could have a null pointer. That's one you could easily check for and do something about.
You could have a pointer to somewhere outside of valid memory. What constitutes valid memory varies depending on how the run-time environment of your system sets up the address space. On Unix systems, it is usually a virtual address space starting at 0 and going to some large number of megabytes. On embedded systems, it could be quite small. It might not start at 0, in any case. If your app happens to be running in supervisor mode or the equivalent, then your pointer might reference a real address, which may or may not be backed up with real memory.
You could have a pointer to somewhere inside your valid memory, even inside your data segment, bss, stack or heap, but not pointing at a valid object. A variant of this is a pointer that used to point to a valid object, before something bad happened to the object. Bad things in this context include deallocation, memory corruption, or pointer corruption.
You could have a flat-out illegal pointer, such as a pointer with illegal alignment for the thing being referenced.
The problem gets even worse when you consider segment/offset based architectures and other odd pointer implementations. This sort of thing is normally hidden from the developer by good compilers and judicious use of types, but if you want to pierce the veil and try to outsmart the operating system and compiler developers, well, you can, but there is not one generic way to do it that will handle all of the issues you might run into.
The best thing you can do is allow the crash and put out some good diagnostic information.
In general, it's impossible to do. Here's one particularly nasty case:
struct Point2d {
int x;
int y;
};
struct Point3d {
int x;
int y;
int z;
};
void dump(Point3 *p)
{
printf("[%d %d %d]\n", p->x, p->y, p->z);
}
Point2d points[2] = { {0, 1}, {2, 3} };
Point3d *p3 = reinterpret_cast<Point3d *>(&points[0]);
dump(p3);
On many platforms, this will print out:
[0 1 2]
You're forcing the runtime system to incorrectly interpret bits of memory, but in this case it's not going to crash, because the bits all make sense. This is part of the design of the language (look at C-style polymorphism with struct inaddr, inaddr_in, inaddr_in6), so you can't reliably protect against it on any platform.
It's unbelievable how much misleading information you can read in articles above...
And even in microsoft msdn documentation IsBadPtr is claimed to be banned. Oh well - I prefer working application rather than crashing. Even if term working might be working incorrectly (as long as end-user can continue with application).
By googling I haven't found any useful example for windows - found a solution for 32-bit apps,
http://www.codeproject.com/script/Content/ViewAssociatedFile.aspx?rzp=%2FKB%2Fsystem%2Fdetect-driver%2F%2FDetectDriverSrc.zip&zep=DetectDriverSrc%2FDetectDriver%2Fsrc%2FdrvCppLib%2Frtti.cpp&obid=58895&obtid=2&ovid=2
but I need also to support 64-bit apps, so this solution did not work for me.
But I've harvested wine's source codes, and managed to cook similar kind of code which would work for 64-bit apps as well - attaching code here:
#include <typeinfo.h>
typedef void (*v_table_ptr)();
typedef struct _cpp_object
{
v_table_ptr* vtable;
} cpp_object;
#ifndef _WIN64
typedef struct _rtti_object_locator
{
unsigned int signature;
int base_class_offset;
unsigned int flags;
const type_info *type_descriptor;
//const rtti_object_hierarchy *type_hierarchy;
} rtti_object_locator;
#else
typedef struct
{
unsigned int signature;
int base_class_offset;
unsigned int flags;
unsigned int type_descriptor;
unsigned int type_hierarchy;
unsigned int object_locator;
} rtti_object_locator;
#endif
/* Get type info from an object (internal) */
static const rtti_object_locator* RTTI_GetObjectLocator(void* inptr)
{
cpp_object* cppobj = (cpp_object*) inptr;
const rtti_object_locator* obj_locator = 0;
if (!IsBadReadPtr(cppobj, sizeof(void*)) &&
!IsBadReadPtr(cppobj->vtable - 1, sizeof(void*)) &&
!IsBadReadPtr((void*)cppobj->vtable[-1], sizeof(rtti_object_locator)))
{
obj_locator = (rtti_object_locator*) cppobj->vtable[-1];
}
return obj_locator;
}
And following code can detect whether pointer is valid or not, you need probably to add some NULL checking:
CTest* t = new CTest();
//t = (CTest*) 0;
//t = (CTest*) 0x12345678;
const rtti_object_locator* ptr = RTTI_GetObjectLocator(t);
#ifdef _WIN64
char *base = ptr->signature == 0 ? (char*)RtlPcToFileHeader((void*)ptr, (void**)&base) : (char*)ptr - ptr->object_locator;
const type_info *td = (const type_info*)(base + ptr->type_descriptor);
#else
const type_info *td = ptr->type_descriptor;
#endif
const char* n =td->name();
This gets class name from pointer - I think it should be enough for your needs.
One thing which I'm still afraid is performance of pointer checking - in code snipet above there is already 3-4 API calls being made - might be overkill for time critical applications.
It would be good if someone could measure overhead of pointer checking compared for example to C#/managed c++ calls.
It is not a very good policy to accept arbitrary pointers as input parameters in a public API. It's better to have "plain data" types like an integer, a string or a struct (I mean a classical struct with plain data inside, of course; officially anything can be a struct).
Why? Well because as others say there is no standard way to know whether you've been given a valid pointer or one that points to junk.
But sometimes you don't have the choice - your API must accept a pointer.
In these cases, it is the duty of the caller to pass a good pointer. NULL may be accepted as a value, but not a pointer to junk.
Can you double-check in any way? Well, what I did in a case like that was to define an invariant for the type the pointer points to, and call it when you get it (in debug mode). At least if the invariant fails (or crashes) you know that you were passed a bad value.
// API that does not allow NULL
void PublicApiFunction1(Person* in_person)
{
assert(in_person != NULL);
assert(in_person->Invariant());
// Actual code...
}
// API that allows NULL
void PublicApiFunction2(Person* in_person)
{
assert(in_person == NULL || in_person->Invariant());
// Actual code (must keep in mind that in_person may be NULL)
}
Following does work in Windows (somebody suggested it before):
static void copy(void * target, const void* source, int size)
{
__try
{
CopyMemory(target, source, size);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
doSomething(--whatever--);
}
}
The function has to be static, standalone or static method of some class.
To test on read-only, copy data in the local buffer.
To test on write without modifying contents, write them over.
You can test first/last addresses only.
If pointer is invalid, control will be passed to 'doSomething',
and then outside the brackets.
Just do not use anything requiring destructors, like CString.
On Windows I use this code:
void * G_pPointer = NULL;
const char * G_szPointerName = NULL;
void CheckPointerIternal()
{
char cTest = *((char *)G_pPointer);
}
bool CheckPointerIternalExt()
{
bool bRet = false;
__try
{
CheckPointerIternal();
bRet = true;
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
}
return bRet;
}
void CheckPointer(void * A_pPointer, const char * A_szPointerName)
{
G_pPointer = A_pPointer;
G_szPointerName = A_szPointerName;
if (!CheckPointerIternalExt())
throw std::runtime_error("Invalid pointer " + std::string(G_szPointerName) + "!");
}
Usage:
unsigned long * pTest = (unsigned long *) 0x12345;
CheckPointer(pTest, "pTest"); //throws exception
On macOS, you can do this with mach_vm_region, which as well as telling you if a pointer is valid, also lets you validate what access you have to the memory to which the pointer points (read/write/execute). I provided sample code to do this in my answer to another question:
#include <mach/mach.h>
#include <mach/mach_vm.h>
#include <stdio.h>
#include <stdbool.h>
bool ptr_is_valid(void *ptr, vm_prot_t needs_access) {
vm_map_t task = mach_task_self();
mach_vm_address_t address = (mach_vm_address_t)ptr;
mach_vm_size_t size = 0;
vm_region_basic_info_data_64_t info;
mach_msg_type_number_t count = VM_REGION_BASIC_INFO_COUNT_64;
mach_port_t object_name;
kern_return_t ret = mach_vm_region(task, &address, &size, VM_REGION_BASIC_INFO_64, (vm_region_info_t)&info, &count, &object_name);
if (ret != KERN_SUCCESS) return false;
return ((mach_vm_address_t)ptr) >= address && ((info.protection & needs_access) == needs_access);
}
#define TEST(ptr,acc) printf("ptr_is_valid(%p,access=%d)=%d\n", (void*)(ptr), (acc), ptr_is_valid((void*)(ptr),(acc)))
int main(int argc, char**argv) {
TEST(0,0);
TEST(0,VM_PROT_READ);
TEST(123456789,VM_PROT_READ);
TEST(main,0);
TEST(main,VM_PROT_READ);
TEST(main,VM_PROT_READ|VM_PROT_EXECUTE);
TEST(main,VM_PROT_EXECUTE);
TEST(main,VM_PROT_WRITE);
TEST((void*)(-1),0);
return 0;
}
The SEI CERT C Coding Standard recommendation MEM10-C. Define and use a pointer validation function says it is possible to do a check to some degree, especially under Linux OS.
The method described in the link is to keep track of the highest memory address returned by malloc and add a function that tests if someone tries to use a pointer greater than that value. It is probably of limited use.
IsBadReadPtr(), IsBadWritePtr(), IsBadCodePtr(), IsBadStringPtr() for Windows.
These take time proportional to the length of the block, so for sanity check I just check the starting address.
I have seen various libraries use some method to check for unreferenced memory and such. I believe they simply "override" the memory allocation and deallocation methods (malloc/free), which has some logic that keeps track of the pointers. I suppose this is overkill for your use case, but it would be one way to do it.
Technically you can override operator new (and delete) and collect information about all allocated memory, so you can have a method to check if heap memory is valid.
but:
you still need a way to check if pointer is allocated on stack ()
you will need to define what is 'valid' pointer:
a) memory on that address is
allocated
b) memory at that address
is start address of object (e.g.
address not in the middle of huge
array)
c) memory at that address
is start address of object of expected type
Bottom line: approach in question is not C++ way, you need to define some rules which ensure that function receives valid pointers.
There is no way to make that check in C++. What should you do if other code passes you an invalid pointer? You should crash. Why? Check out this link: http://blogs.msdn.com/oldnewthing/archive/2006/09/27/773741.aspx
Addendum to the accpeted answer(s):
Assume that your pointer could hold only three values -- 0, 1 and -1 where 1 signifies a valid pointer, -1 an invalid one and 0 another invalid one. What is the probability that your pointer is NULL, all values being equally likely? 1/3. Now, take the valid case out, so for every invalid case, you have a 50:50 ratio to catch all errors. Looks good right? Scale this for a 4-byte pointer. There are 2^32 or 4294967294 possible values. Of these, only ONE value is correct, one is NULL, and you are still left with 4294967292 other invalid cases. Recalculate: you have a test for 1 out of (4294967292+ 1) invalid cases. A probability of 2.xe-10 or 0 for most practical purposes. Such is the futility of the NULL check.
You know, a new driver (at least on Linux) that is capable of this probably wouldn't be that hard to write.
On the other hand, it would be folly to build your programs like this. Unless you have some really specific and single use for such a thing, I wouldn't recommend it. If you built a large application loaded with constant pointer validity checks it would likely be horrendously slow.
you should avoid these methods because they do not work. blogs.msdn.com/oldnewthing/archive/2006/09/27/773741.aspx – JaredPar Feb 15 '09 at 16:02
If they don't work - next windows update will fix it ?
If they don't work on concept level - function will be probably removed from windows api completely.
MSDN documentation claim that they are banned, and reason for this is probably flaw of further design of application (e.g. generally you should not eat invalid pointers silently - if you're in charge of design of whole application of course), and performance/time of pointer checking.
But you should not claim that they does not work because of some blog.
In my test application I've verified that they do work.
these links may be helpful
_CrtIsValidPointer
Verifies that a specified memory range is valid for reading and writing (debug version only).
http://msdn.microsoft.com/en-us/library/0w1ekd5e.aspx
_CrtCheckMemory
Confirms the integrity of the memory blocks allocated in the debug heap (debug version only).
http://msdn.microsoft.com/en-us/library/e73x0s4b.aspx

practical explanation of c++ functions with pointers

I am relatively new to C++...
I am learning and coding but I am finding the idea of pointers to be somewhat fuzzy. As I understand it * points to a value and & points to an address...great but why? Which is byval and which is byref and again why?
And while I feel like I am learning and understanding the idea of stack vs heap, runtime vs design time etc, I don't feel like I'm fully understanding what is going on. I don't like using coding techniques that I don't fully understand.
Could anyone please elaborate on exactly what and why the pointers in this fairly "simple" function below are used, esp the pointer to the function itself.. [got it]
Just asking how to clean up (delete[]) the str... or if it just goes out of scope.. Thanks.
char *char_out(AnsiString ansi_in)
{
// allocate memory for char array
char *str = new char[ansi_in.Length() + 1];
// copy contents of string into char array
strcpy(str, ansi_in.c_str());
return str;
}
Revision 3
TL;DR:
AnsiString appears to be an object which is passed by value to that function.
char* str is on the stack.
A new array is created on the heap with (ansi_in.Length() + 1) elements. A pointer to the array is stored in str. +1 is used because strings in C/C++ typically use a null terminator, which is a special character used to identify the end of the string when scanning through it.
ansi_in.cstr() is called, copying a pointer to its string buffer into an unnamed local variable on the stack.
str and the temporary pointer are pushed onto the stack and strcpy is called. This has the effect of copying the string(including the null-terminator) pointed at from the temporary to str.
str is returned to the caller
Long answer:
You appear to be struggling to understand stack vs heap, and pointers vs non-pointers. I'll break them down for you and then answer your question.
The stack is a concept where a fixed region of memory is allocated for each thread before it starts and before any user code runs.
Ignoring lower level details such as calling conventions and compiler optimizations, you can reason that the following happens when you call a function:
Arguments are pushed onto the stack. This reserves part of the stack for use of the arguments.
The function performs some job, using and copying the arguments as needed.
The function pops the arguments off the stack and returns. This frees the space reserved for the arguments.
This isn't limited to function calls. When you declare objects and primitives in a function's body, space for them is reserved via pushing. When they're out of scope, they're automatically cleaned up by calling destructors and popping.
When your program runs out of stack space and starts using the space outside of it, you'll typically encounter an error. Regardless of what the actual error is, it's known as a stack overflow because you're going past it and therefore "overflowing".
The heap is a different concept where the remaining unused memory of the system is available for you to manually allocate and deallocate from. This is primarily used when you have a large data set that's too big for the stack, or when you need data to persist across arbitrary functions.
C++ is a difficult beast to master, but if you can wrap your head around the core concepts is becomes easier to understand.
Suppose we wanted to model a human:
struct Human
{
const char* Name;
int Age;
};
int main(int argc, char** argv)
{
Human human;
human.Name = "Edward";
human.Age = 30;
return 0;
}
This allocates at least sizeof(Human) bytes on the stack for storing the 'human' object. Right before main() returns, the space for 'human' is freed.
Now, suppose we wanted an array of 10 humans:
int main(int argc, char** argv)
{
Human humans[10];
humans[0].Name = "Edward";
humans[0].Age = 30;
// ...
return 0;
}
This allocates at least (sizeof(Human) * 10) bytes on the stack for storing the 'humans' array. This too is automatically cleaned up.
Note uses of ".". When using anything that's not a pointer, you access their contents using a period. This is direct memory access if you're not using a reference.
Here's the single object version using the heap:
int main(int argc, char** argv)
{
Human* human = new Human();
human->Name = "Edward";
human->Age = 30;
delete human;
return 0;
}
This allocates sizeof(Human*) bytes on the stack for the pointer 'human', and at least sizeof(Human) bytes on the heap for storing the object it points to. 'human' is not automatically cleaned up, you must call delete to free it. Note uses of "a->b". When using pointers, you access their contents using the "->" operator. This is indirect memory access, because you're accessing memory through an variable address.
It's sort of like mail. When someone wants to mail you something they write an address on an envelope and submit it through the mail system. A mailman takes the mail and moves it to your mailbox. For comparison the pointer is the address written on the envelope, the memory management unit(mmu) is the mail system, the electrical signals being passed down the wire are the mailman, and the memory location the address refers to is the mailbox.
Here's the array version using the heap:
int main(int argc, char** argv)
{
Human* humans = new Human[10];
humans[0].Name = "Edward";
humans[0].Age = 30;
// ...
delete[] humans;
return 0;
}
This allocates sizeof(Human*) bytes on the stack for pointer 'humans', and (sizeof(Human) * 10) bytes on the heap for storing the array it points to. 'humans' is also not automatically cleaned up; you must call delete[] to free it.
Note uses of "a[i].b" rather than "a[i]->b". The "[]" operator(indexer) is really just syntactic sugar for "*(a + i)", which really just means treat it as a normal variable in a sequence so I can type less.
In both of the above heap examples, if you didn't write delete/delete[], the memory that the pointers point to would leak(also known as dangle). This is bad because if left unchecked it could eat through all your available memory, eventually crashing when there isn't enough or the OS decides other apps are more important than yours.
Using the stack is usually the wiser choice as you get automatic lifetime management via scope(aka RAII) and better data locality. The only "drawback" to this approach is that because of scoped lifetime you can't directly access your stack variables once the scope has exited. In other words you can only use stack variables within the scope they're declared. Despite this, C++ allows you to copy pointers and references to stack variables, and indirectly use them outside the scope they're declared in. Do note however that this is almost always a very bad idea, don't do it unless you really know what you're doing, I can't stress this enough.
Passing an argument by-ref means pushing a copy of a pointer or reference to the data on the stack. As far as the computer is concerned pointers and references are the same thing. This is a very lightweight concept, but you typically need to check for null in functions receiving pointers.
Pointer variant of an integer adding function:
int add(const int* firstIntPtr, const int* secondIntPtr)
{
if (firstIntPtr == nullptr) {
throw std::invalid_argument("firstIntPtr cannot be null.");
}
if (secondIntPtr == nullptr) {
throw std::invalid_argument("secondIntPtr cannot be null.");
}
return *firstIntPtr + *secondIntPtr;
}
Note the null checks. If it didn't verify its arguments are valid, they very well may be null or point to memory the app doesn't have access to. Attempting to read such values via dereferencing(*firstIntPtr/*secondIntPtr) is undefined behavior and if you're lucky results in a segmentation fault(aka access violation on windows), crashing the program. When this happens and your program doesn't crash, there are deeper issues with your code that are out of the scope of this answer.
Reference variant of an integer adding function:
int add(const int& firstInt, const int& secondInt)
{
return firstInt + secondInt;
}
Note the lack of null checks. By design C++ limits how you can acquire references, so you're not suppose to be able to pass a null reference, and therefore no null checks are required. That said, it's still possible to get a null reference through converting a pointer to a reference, but if you're doing that and not checking for null before converting you have a bug in your code.
Passing an argument by-val means pushing a copy of it on the stack. You almost always want to pass small data structures by value. You don't have to check for null when passing values because you're passing the actual data itself and not a pointer to it.
i.e.
int add(int firstInt, int secondInt)
{
return firstInt + secondInt;
}
No null checks are required because values, not pointers are used. Values can't be null.
Assuming you're interested in learning about all this, I highly suggest you use std::string(also see this) for all your string needs and std::unique_ptr(also see this) for managing pointers.
i.e.
std::string char_out(AnsiString ansi_in)
{
return std::string(ansi_in.c_str());
}
std::unique_ptr<char[]> char_out(AnsiString ansi_in)
{
std::unique_ptr<char[]> str(new char[ansi_in.Length() + 1]);
strcpy(str.get(), ansi_in.c_str());
return str; // std::move(str) if you're using an older C++11 compiler.
}

Different categories of memory

static const int MAX_SIZE = 256; //I assume this is static Data
bool initialiseArray(int* arrayParam, int sizeParam) //where does this lie?
{
if(size > MAX_SIZE)
{
return false;
}
for(int i=0; i<sizeParam; i++)
{
arrayParam[i] = 9;
}
return true;
}
void main()
{
int* myArray = new int[30]; //I assume this is allocated on heap memory
bool res = initialiseArray(myArray, 30); //Where does this lie?
delete myArray;
}
We're currently learning the different categories of memory, i know that theres
-Code Memory
-Static Data
-Run-Time Stack
-Free Store(Heap)
I have commented where im unsure about, just wondering if anyone could help me out. My definition for the Run-Time stack describes that this is used for functions but my code memory defines that it contains all instructions for the methods/functions so im just a bit confused.
Can anyone lend a hand?
static const int MAX_SIZE = 256; //I assume this is static Data
Yes indeed. In fact, because it's const, this value might not be kept in your final executable at all, because the compiler can just substitute "256" anywhere it sees MAX_SIZE.
bool initialiseArray(int* arrayParam, int sizeParam) //where does this lie?
The code for the initialiseArray() function will be in the data section of your exectuable. You can get a pointer to the memory address, and call the function via that address, but other than that there's not much else you can do with it.
The arrayParam and sizeParam arguments will be passed to the function by value, on the stack. Likewise, the bool return value will be placed into the calling function's stack area.
int* myArray = new int[30]; //I assume this is allocated on heap memory
Correct.
bool res = initialiseArray(myArray, 30); //Where does this lie?
Effectively, the myArray pointer and the literal 30 are copied into the stack area of initialiseArray(), which then operates on them, and then the resulting bool is copied into the stack area of the calling function.
The actual details of argument passing are a lot more grizzly and depend on calling conventions (of which there are several, particularly on Windows), but unless you're doing something really specialised then they're not really important :-)
The stack is used for automatic variables - that is, variables declared within functions, or as function parameters. These variables are destroyed automatically when the program leaves the block of code they were declared in.
You're correct that MAX_SIZE has a static lifetime - it is destroyed automatically at the end of the program. You're also correct that the array allocated with new[] is on the heap (having a dynamic lifetime) - it won't be destroyed automatically, so need to be deleted. By the way, you need delete [] myArray; to match the use of new [].
The pointer to it (myArray) is an automatic variable, on the stack, as are res and the function arguments.
There is just one type of memory... it is a memory :D
What is different is where it is and how you access it.
If you go deep into the exe loader in Windows ( or in any kind of OS actually ) what it really does is that is stores the information of your sections ( parts of you exe ) and at run time at lays it out properly into the memory and applies access rights. So generally the code section where your "program" is the same memory ( your RAM ) as your data section. The difference is that the access rights are different, the code section usually only have read + execute the data just read + write ( and no execute ).
The stack is still a memory, it is special in the sense that it is again controlled by the OS, the stack size is the size in bytes of how big your stack is, but here the purpose is to hold immediate values between function calls ( as per stdcall ) and local variables ( depends on the compiler how it does it exactly ) so because it is a memory you CAN use it but like you it is to to lets say allocate a 10000 byte string on the stack. In assembly you have direct access since there is a stack pointer EBP ( If I remember correctly :P ) or in C/C++ you can use alloca.
The new and the delete operators are built ins for the C++ language but as far as I know they use the same system allocators as you do, in fact you can override them and use malloc/free and it should work which means that again this is the same memory.
The difference between using new/delete and an os specific function is that you let the language handle the allocation but in the end you will get a pointer just like you would with any other function.
On top of this there are special ways but those change the way the memory handled, in Windows this is the virtual memory for example, like VirutalAlloc, VirutalFree will allow you specify what you will do with the memory you want to use thus you allow the OS to optimize better, like you tell it I want 2Gb of memory BUT it doesn't have to be in RAM, so it may save it on the disk but you STILL access this with memory pointers.
And about your questions :
static const int MAX_SIZE = 256; //I assume this is static Data
It usually depends on the compiler but mostly they will treat this as const ( static is something else ) which means that it will be in the const section of the exe which in turn means that this memory block will be read-only.
int* myArray = new int[30]; //I assume this is allocated on heap memory
Yes this will be on the heap, but how it is allocated depends on the implementation and whenever you override the new operator, if you do you can for example force it to be in the Virtual memory so in fact it could be on the disk or in RAM, but this is silly thing to do so yes it will be on the heap.
bool res = initialiseArray(myArray, 30); //Where does this lie?
Multiple things happen here, because the compiler know that the first parameter of initialiseArray must be a pointer to an int it will pass a pointer to myArray so both a pointer and the value of 30 will go on the stack and then the function is called.
In the function which is in the memory ( the code section ) it runs and gets the parameters ( int* arrayParam, int sizeParam ) from the stack it will know that you want to write to the arrayParam and that is is pointer so it will write into the location arrayParam points to. To where exactly you specify it with arrayParam[i] < i will offset the memory pointer to the correct value, again C++ does some magic by adjusting the pointer for you since the adjustment in code should be in bytes it will move the memory pointer by 4 since ( usually ) int == 4 bytes.
To get a better overview of where goes what and how it works, use a debugger or a disassembler ( like OllyDbg ) and see it for yourself, if you want know more about how the stack is used look up the stdcall calling convention.

C++ - Regarding the scope of dynamic arrays

I have a quick question regarding the scope of dynamic arrays, which I assume is causing a bug in a program I'm writing. This snippet checks a function parameter and branches to either the first or the second, depending on what the user passes.
When I run the program, however, I get a scope related error:
error: ‘Array’ was not declared in this scope
Unless my knowledge of C++ fails me, I know that variables created within a conditional fall out of scope when when the branch is finished. However, I dynamically allocated these arrays, so I cannot understand why I can't manipulate the arrays later in the program, since the pointer should remain.
//Prepare to store integers
if (flag == 1) {
int *Array;
Array = new int[input.length()];
}
//Prepare to store chars
else if (flag == 2) {
char *Array;
Array = new char[input.length()];
}
Can anyone shed some light on this?
Declare Array before if. And you can't declare array of different types as one variable, so I think you should use to pointers.
int *char_array = nullptr;
int *int_array = nullptr;
//Prepare to store integers
if (flag == 1) {
int_array = new int[input.length()];
}
//Prepare to store chars
else if (flag == 2) {
char_array = new char[input.length()];
}
if (char_array)
{
//do something with char_array
}
else if (int_array)
{
//do something with int_array
}
Also as j_random_hacker points, you might want to change you program design to avoid lot's of if
While you are right that since you dynamically allocated them on the heap, the memory won't be released to the system until you explicitly delete it (or the program ends), the pointer to the memory falls out of scope when the block it was declared in exits. Therefore, your pointer(s) need to exist at a wider scope if they will be used after the block.
The memory remains allocated (i.e. taking up valuable space), there's just no way to access it after the closing }, because at that point the program loses the ability to address it. To avoid this, you need to assign the pointer returned by new[] to a pointer variable declared in an outer scope.
As a separate issue, it looks as though you're trying to allocate memory of one of 2 different types. If you want to do this portably, you're obliged to either use a void * to hold the pointer, or (less commonly done) a union type containing a pointer of each type. Either way, you will need to maintain state information that lets the program know which kind of allocation has been made. Usually, wanting to do this is an indication of poor design, because every single access will require switching on this state information.
If I understand your intend correctly what you are trying to do is: depending on some logic allocate memory to store n elements of either int or char and then later in your function access that array as either int or char without the need for a single if statement.
If the above understanding is correct than the simple answer is: "C++ is a strong-typed language and what you want is not possible".
However... C++ is also an extremely powerful and flexible language, so here's what can be done:
Casting. Something like the following:
void * Array;
if(flag1) Array = new int[len]
else Array = new char[len];
// ... later in the function
if(flag) // access as int array
int i = ((int*)Array)[0];
Yes, this is ugly and you'll have to have those ifs sprinkled around the function. So here's an alternative: template
template<class T> T foo(size_t _len)
{
T* Array = new T[_len];
T element = Array[0];
return element;
}
Yet another, even more obscure way of doing things, could be the use of unions:
union int_or_char {int i; char c;};
int_or_char *Array = new int_or_char[len];
if(flag) // access as int
int element = Array[0].i;
But one way or the other (or the third) there's no way around the fact that the compiler has to know how to deal with the data you are trying to work with.
Turix's answer is right. You need to keep in mind that two things are being allocated here, The memory for the array and the memory when the location of the array is stored.
So even though the memory from the array is allocated from the heap and will be available to the code where ever required, the memory where the location of the array is stored (the Array variable) is allocated in the stack and will be lost as soon as it goes out of scope. Which in this case is when the if block end. You can't even use it in the else part of the same if.
Another different code suggestion from Andrew I would give is :
void *Array = nullptr;
if (flag == 1) {
Array = new int[input.length()];
} else if (flag == 2) {
Array = new char[input.length()];
}
Then you can directly use if as you intended.
This part I am not sure : In case you want to know if its an int or char you can use the typeid literal. Doesn't work, at least I can't get it to work.
Alternatively you can use your flag variable to guess what type it is.

C++ string manipulation

My lack of C++ experience, or rather my early learning in garbage collected languages is really stinging me at the moment and I have a problem working with strings in C++.
To make it very clear, using std::string or equlivents is not an option - this is char* 's all the way.
So: what I need to do is very simple and basically boils down to concatenating strings. At runtime I have 2 classes.
One class contains "type" information in the form of a base filename.
in the header:
char* mBaseName;
and later, in the .cpp it is loaded with info passed in from elsewhere.
mBaseName = attributes->BaseName;
The 2nd class provides version information in the form of a suffix to the base file name, it's a static class and implemented like this at present:
static const char* const suffixes[] = {"Version1", "Version", "Version3"}; //etc.
static char* GetSuffix()
{
int i = 0;
//perform checks on some data structures
i = somevalue;
return suffixes[i];
}
Then, at runtime the base class creates the filename it needs:
void LoadStuff()
{
char* suffix = GetSuffix();
char* nameToUse = new char[50];
sprintf(nameToUse, "%s%s",mBaseName,suffix);
LoadAndSetupData(nameToUse);
}
And you can see the problem immediately. nameToUse never gets deleted, memory leak.
The suffixes are a fixed list, but the basefilenames are arbitrary. The name that is created needs to persist beyond the end of "LoadStuff()" as it's not clear when if and how it is used subsequently.
I am probably worrying too much, or being very stupid, but similar code to LoadStuff() happens in other places too, so it needs solving. It's frustrating as I don't quite know enough about the way things work to see a safe and "un-hacky" solution. In C# I'd just write:
LoadAndSetupData(mBaseName + GetSuffix());
and wouldn't need to worry.
Any comments, suggestions, or advice much appreciated.
Update
The issue with the code I am calling LoadAndSetupData() is that, at some point it probably does copy the filename and keep it locally, but the actual instantiation is asynchranous, LoadAndSetupData actually puts things into a queue, and at that point at least, it expects that the string passed in still exists.
I do not control this code so I can't update it's function.
Seeing now that the issue is how to clean up the string that you created and passed to LoadAndSetUpData()
I am assuming that:
LoadAndSetUpData() does not make its own copy
You can't change LoadAndSetUpData() to do that
You need the string to still exist for some time after LoadAndSetupData() returns
Here are suggestions:
Can you make your own queue objects to be called? Are they guaranteed to be called after the ones that use your string. If so, create cleanup queue events with the same string that call delete[] on them
Is there a maximum number you can count on. If you created a large array of strings, could you use them in a cycle and be assured that when you got back to the beginning, it would be ok to reuse that string
Is there an amount of time you can count on? If so, register them for deletion somewhere and check that after some time.
The best thing would be for functions that take char* to take ownership or copy. Shared ownership is the hardest thing to do without reference counting or garbage collection.
EDIT: This answer doesn't address his problem completely -- I made other suggestions here:
C++ string manipulation
His problem is that he needs to extend the scope of the char* he created to outside the function, and until an asynchronous job is finished.
Original Answer:
In C++, if I can't use the standard library or Boost, I still have a class like this:
template<class T>
class ArrayGuard {
public:
ArrayGuard(T* ptr) { _ptr = ptr; }
~ArrayGuard() { delete[] _ptr; }
private:
T* _ptr;
ArrayGuard(const ArrayGuard&);
ArrayGuard& operator=(const ArrayGuard&);
}
You use it like:
char* buffer = new char[50];
ArrayGuard<char *> bufferGuard(buffer);
The buffer will be deleted at the end of the scope (on return or throw).
For just simple array deleting for dynamic sized arrays that I want to be treated like a static sized array that gets released at the end of the scope.
Keep it simple -- if you need fancier smart pointers, use Boost.
This is useful if the 50 in your example is variable.
The thing to remember with C++ memory management is ownership. If the LoadAndSetupData data is not going to take ownership of the string, then it's still your responsibility. Since you can't delete it immediately (because of the asynchronicity issue), you're going to have to hold on to those pointers until such time as you know you can delete them.
Maintain a pool of strings that you have created:
If you have some point in time where you know that the queue has been completely dealt with, you can simply delete all the strings in the pool.
If you know that all strings created after a certain point in time have been dealt with, then keep track of when the strings were created, and you can delete that subset. - If you can somehow find out when an individual string has been dealt with, then just delete that string.
class StringPool
{
struct StringReference {
char *buffer;
time_t created;
} *Pool;
size_t PoolSize;
size_t Allocated;
static const size_t INITIAL_SIZE = 100;
void GrowBuffer()
{
StringReference *newPool = new StringReference[PoolSize * 2];
for (size_t i = 0; i < Allocated; ++i)
newPool[i] = Pool[i];
StringReference *oldPool = Pool;
Pool = newPool;
delete[] oldPool;
}
public:
StringPool() : Pool(new StringReference[INITIAL_SIZE]), PoolSize(INITIAL_SIZE)
{
}
~StringPool()
{
ClearPool();
delete[] Pool;
}
char *GetBuffer(size_t size)
{
if (Allocated == PoolSize)
GrowBuffer();
Pool[Allocated].buffer = new char[size];
Pool[Allocated].buffer = time(NULL);
++Allocated;
}
void ClearPool()
{
for (size_t i = 0; i < Allocated; ++i)
delete[] Pool[i].buffer;
Allocated = 0;
}
void ClearBefore(time_t knownCleared)
{
size_t newAllocated = 0;
for (size_t i = 0; i < Allocated; ++i)
{
if (Pool[i].created < knownCleared)
{
delete[] Pool[i].buffer;
}
else
{
Pool[newAllocated] = Pool[i];
++newAllocated;
}
}
Allocated = newAllocated;
}
// This compares pointers, not strings!
void ReleaseBuffer(char *knownCleared)
{
size_t newAllocated = 0;
for (size_t i = 0; i < Allocated; ++i)
{
if (Pool[i].buffer == knownCleared)
{
delete[] Pool[i].buffer;
}
else
{
Pool[newAllocated] = Pool[i];
++newAllocated;
}
}
Allocated = newAllocated;
}
};
Since std::string is not an option, for whatever reason, have you looked into smart pointers? See boost
But I can only encourage you to use std::string.
Christian
If you must use char*'s, then LoadAndSetupData() should explicitly document who owns the memory for the char* after the call. You can do one of two things:
Copy the string. This is probably the simplest thing. LoadAndSetupData copies the string into some internal buffer, and the caller is always responsible for the memory.
Transfer ownership. LoadAndSetupData() documents that it will be responsible for eventually freeing the memory for the char*. The caller doesn't need to worry about freeing the memory.
I generally prefer safe copying as in #1, because the allocator of the string is also responsible for freeing it. If you go with #2, the allocator has to remember NOT to free things, and memory management happens in two places, which I find harder to maintain. In either case, it's a matter of explicitly documenting the policy so that the caller knows what to expect.
If you go with #1, take a look at Lou Franco's answer to see how you might allocate a char[] in an exception-safe, sure to be freed way using a guard class. Note that you can't (safely) use std::auto_ptr for arrays.
Since you need nameToUse to still exist after the function, you are stuck using new, what I would do is return a pointer to it, so the caller can "delete" it at a later time when it is no longer needed.
char * LoadStuff()
{
char* suffix = GetSuffix();
char* nameToUse = new char[50];
sprintf("%s%s",mBaseName,suffix);
LoadAndSetupData(nameToUse);
return nameToUse;
}
then:
char *name = LoadStuff();
// do whatever you need to do:
delete [] name;
There is no need to allocate on heap in this case. And always use snprintf:
char nameToUse[50];
snprintf(nameToUse, sizeof(nameToUse), "%s%s",mBaseName,suffix);
Where exactly nameToUse is used beyond the scope of LoadStuff? If someone needs it after LoadStuff it needs to pass it, along with the responisbility for memory deallocation
If you would have done it in c# as you suggested
LoadAndSetupData(mBaseName + GetSuffix());
then nothing would reference LoadAndSetupData's parameter, therefore you can safely change it to
char nameToUse[50];
as Martin suggested.
You're going to have to manage the lifetime of the memory you allocate for nameToUse. Wrapping it up in a class such as std::string makes your life a bit simpler.
I guess this is a minor outrage, but since I can't think of any better solution to your problem, I'll point out another potential problem. You need to be very careful to check the size of the buffer you're writing into when copying or concatenating strings. Functions such as strcat, strcpy and sprintf can easily overwrite the end of their target buffers, leading to spurious runtime errors and security vulnerabilities.
Apologies, my own experience is mostly on the Windows platform, where they introduced "safe" versions of these functions, called strcat_s, strcpy_s, and sprintf_s. The same goes for all their many related functions.
First: Why do you need for the allocated string to persist beyond the end of LoadStuff()? Is there a way you can refactor to remove that requirement.
Since C++ doesn't provide a straightforward way to do this kind of stuff, most programming environments use a set of guidelines about pointers to prevent delete/free problems. Since things can only be allocated/freed once, it needs to be very clear who "owns" the pointer. Some sample guidelines:
1) Usually the person that allocates the string is the owner, and is also responsible for freeing the string.
2) If you need to free in a different function/class than you allocated in, there must be an explicit hand-off of ownership to another class/function.
3) Unless explicitly stated otherwise, pointers (including strings) belong to the caller. A function, constructor, etc. cannot assume that the string pointer it gets will persist beyond the end of the function call. If they need a persistent copy of the pointer, they should make a local copy with strdup().
What this boils down to in your specific case is that LoadStuff() should delete[] nameToUse, and the function that it calls should make a local copy.
One alternate solution: if nameToUse is going to be passed lots of places and needs to persist for the lifetime of the program, you could make it a global variable. (This saves the trouble of making lots of copies of it.) If you don't want to pollute your global namespace, you could just declare it static local to the function:
static char *nameToUse = new char[50];
Thankyou everyone for your answers. I have not selected one as "the answer" as there isn't a concrete solution to this problem and the best discussions on it are all upvoted be me and others anyway.
Your suggestions are all good, and you have been very patient with the clunkiness of my question. As I am sure you can see, this is a simplification of a more complicated problem and there is a lot more going on which is connected with the example I gave, hence the way that bits of it may not have entirely made sense.
For your interest I have decided to "cheat" my way out of the difficulty for now. I said that the base names were arbitrary, but this isn't quite true. In fact they are a limited set of names too, just a limited set that could change at some point, so I was attempting to solve a more general problem.
For now I will extend the "static" solution to suffixes and build a table of possible names. This is very "hacky", but will work and moreover avoids refactoring a large amount of complex code which I am not able to.
Feedback has been fantastic, many thanks.
You can combine some of the ideas here.
Depending on how you have modularized your application, there may be a method (main?) whose execution determines the scope in which nameToUse is definable as a fixed size local variable. You can pass the pointer (&nameToUse[0] or simply nameToUse) to those other methods that need to fill it (so pass the size too) or use it, knowing that the storage will disappear when the function having the local variable exits or your program terminates by any other means.
There is little difference between this and using dynamic allocation and deletion (since the pointer holding the location will have to be managed more-or-less the same way). The local allocation is more direct in many cases and is very inexpensive when there is no problem with associating the maximum-required lifetime with the duration of a particular function's execution.
I'm not totally clear on where LoadAndSetupData is defined, but it looks like it's keeping its own copy of the string. So then you should delete your locally allocated copy after the call to LoadAndSetupData and let it manage its own copy.
Or, make sure LoadAndSetupData cleans up the allocated char[] that you give it.
My preference would be to let the other function keep its own copy and manage it so that you don't allocate an object for another class.
Edit: since you use new with a fixed size [50], you might as well make it local as has been suggested and the let LoadAndSetupData make its own copy.