I guess there is problem with the relation of malloc and goto. Or, I guess there is some wastage of memory or corruption of memory happening out here. Hope, someone can point to me the exact error.
When I compile its not giving me any error, but, my senior is insisting that I have a mistake.
#define FINISH() goto fini;
BOOL Do()
{
BOOL stat;
UINT32 ptr;
int err;
ptr = (UINT32)malloc(1000);
free((void*)ptr);
fini:
return stat;
}
Here are the problems I spotted in the code
When err != ERROR_SUCCESS this function will leak memory. It will jump over the free call.
You are storing the return of malloc into a 32 bit location. This is not a portable solution. On 64 bit platforms this will wreak havoc on your program as you'd be truncating the address. If you must use a non-pointer type here use size_t instead (although I would reccomend a pointer over an integral type)
The local stat is not definitively assigned here. You are returning garbage if err != ERROR_SUCCESS. It needs to always be assigned a value. Easiest way is provide a default.
You don't check the return value of malloc and potentially pass a hidden NULL pointer into Fun2
Here's the function with the edits I suggested
BOOL Do()
{
BOOL stat = FALSE;
size_t ptr = 0;
int err;
ptr = (UINT32)malloc(1000);
err = Fun1();
if (err != ERROR_SUCCESS || ptr == 0)
FINISH();
else
stat = Fun2(ptr);
fini:
free((void*)ptr);
return stat;
}
malloc returns a pointer. You are casting a pointer to an integer but pointers and integers are not required to have the same representation. For example the pointer size could be 64-bit and would not fit in your integer.
Also the object stat can be used not-initialized in your function. Without an explicit initialized the object stat has an indeterminate value after its declaration.
We have no idea what this is supposed to do, but if Fun1() doesn't return ERROR_SUCCESS, then ptr is never freed. Presumably, that's the error your boss is talking about.
You are converting a pointer to an uint32_t and back again. This erases the upper half of your pointer value.
Whatever you do, you are not compiling that code. It has a syntax error.
if(foo)
bar;;
else
baz
Check your build system.
My overall comment, and a general rule of thumb for working in C... If you have to do pointer casts, ask yourself: do you really have to? The times you will honestly need to do pointer casts are exceedingly rare. What's much more common is when people use pointer casts because they have some gap in understanding, don't have it very clear what they're trying to do or should be doing, and are trying to silence a compiler warning.
ptr = (UINT32)malloc(1000);
Very bad! If you do anything with this "pointer", you will be very lucky if it works on 64-bit plaforms. Leave pointers as pointer types. If you absolutely must store them in an integer, use uintptr_t which is guaranteed to be large enough.
I'd say you might have been trying to do:
// Allocate 1,000 32-bit integers
UINT32 *ptr = (UINT32*)malloc(1000 * sizeof(UINT32));
However even that is poor form for C code, a weird C and C++ hybrid. Unlike C++, in C you can just take a void * and implicitly bring it to any pointer type:
// Allocate 1,000 32-bit integers
UINT32 *ptr = malloc(1000 * sizeof(UINT32));
Lastly,
free((void*)ptr);
Casting to void* is another big red flag, frequently a sign that the author doesn't know what they're doing. Once you change ptr to be an actual pointer type, just do this:
free(ptr);
Related
I'm trying to understand C-pointers. As background, I'm used to coding in both C# and Python3.
I understand that pointers can be used to save the addresses of a variable (writing something like type* ptr = &var;) and that incrementing pointers is equivalent to incrementing the index of an array of objects of that object type type. But what I don't understand is whether or not you can use pointers and deferenced objects of the type (e.g. int) without referencing an already-defined variable.
I couldn't think of a way to do this, and most of the examples of C/C++ pointers all seem to use them to reference a variable. So it might be that what I'm asking is either impossible and/or bad coding practice. If so, it would be helpful to understand why.
For example, to clarify my confusion, if there is no way to use pointers without using predefined hard-coded variables, why would you use pointers at all instead of the basic object directly, or arrays of objects?
There is a short piece of code below to describe my question formally.
Many thanks for any advice!
// Learning about pointers and C-coding techniques.
#include <stdio.h>
/* Is there a way to define the int-pointer age WITHOUT the int variable auxAge? */
int main() // no command-line params being passed
{
int auxAge = 12345;
int* age = &auxAge;
// *age is an int, and age is an int* (i.e. age is a pointer-to-an-int, just an address to somewhere in memory where data defining some int is expected)
// do stuff with my *age int e.g. "(*age)++;" or "*age = 37;"
return 0;
}
Yes, you can use dynamic memory (also known as "heap") allocation:
#include <stdlib.h>
int * const integer = malloc(sizeof *integer);
if (integer != NULL)
{
*integer = 4711;
printf("forty seven eleven is %d\n", *integer);
free(integer);
// At this point we can no longer use the pointer, the memory is not ours any more.
}
This asks the C library to allocate some memory from the operating system and return a pointer to it. Allocating sizeof *integer bytes makes the allocation fit an integer exactly, and we can then use *integer to dereference the pointer, that will work pretty much exactly like referencing an integer directly.
There are many good reasons to use pointers in C, and one of them is, that you can only pass by value in C - you cannot pass by reference. Therefore passing pointer to an existing variable saves you the overhead of copying it to stack. As an example, let's assume this very large structure:
struct very_large_structure {
uint8_t kilobyte[1024];
}
And now assume a function which needs to use this structure:
bool has_zero(struct very_large_structure structure) {
for (int i = 0; i < sizeof(structure); i++) {
if (0 == structure.kilobyte[i]) {
return true;
}
}
return false;
}
So for this function to be called, you need to copy the whole structure to stack, and that can be especially on embedded platforms where C is widely used an unacceptable requirement.
If you will pass the structure via pointer, you are only copying to the stack the pointer itself, typically a 32-bit number:
bool has_zero(struct very_large_structure *structure) {
for (int i = 0; i < sizeof(*structure); i++) {
if (0 == structure->kilobyte[i]) {
return true;
}
}
return false;
}
This is by no mean the only and most important use of pointers, but it clearly shows the reasoning why pointers are important in C.
But what I don't understand is whether or not you can use pointers and deferenced objects of the type (e.g. int) without referencing an already-defined variable.
Yes, there are two cases where this is possible.
The first case occurs with dynamic memory allocation. You use the malloc, calloc, or realloc functions to allocate memory from a dynamic memory pool (the "heap"):
int *ptr = malloc( sizeof *ptr ); // allocate enough memory for a single `int` object
*ptr = some_value;
The second case occurs where you have a fixed, well-defined address for an I/O channel or port or something:
char *port = (char *) OxDEADBEEF;
although this is more common in embedded systems than general applications programming.
EDIT
Regarding the second case, chapter and verse:
6.3.2.3 Pointers
...
5 An integer may be converted to any pointer type. Except as previously specified, the
result is implementation-defined, might not be correctly aligned, might not point to an
entity of the referenced type, and might be a trap representation.67)
67) The mapping functions for converting a pointer to an integer or an integer to a pointer are intended to
be consistent with the addressing structure of the execution environment.
Parameters to a function in C are always pass by value, so changing a parameter value in a function isn't reflected in the caller. You can however use pointers to emulate pass by reference. For example:
void clear(int *x)
{
*x = 0;
}
int main()
{
int a = 4;
printf("a=%d\n", a); // prints 4
clear(&a);
printf("a=%d\n", a); // prints 0
return 0;
}
You can also use pointers to point to dynamically allocated memory:
int *getarray(int size)
{
int *array = malloc(size * sizeof *array);
if (!array) {
perror("malloc failed");
exit(1);
}
return array;
}
These are just a few examples.
Most common reason: because you wish to modify the contents without passing them around.
Analogy:
If you want your living room painted, you don't want to place your house on a truck trailer, move it to the painter, let him do the job and then haul it back. It would be expensive and time consuming. And if your house is to wide to get hauled around on the streets, the truck might crash. You would rather tell the painter which address you live on, have him go there and do the job.
In C terms, if you have a big struct or similar, you'll want a function to access this struct without making a copy of it, passing a copy to the function, then copy back the modified contents back into the original variable.
// BAD CODE, DONT DO THIS
typedef struct { ... } really_big;
really_big rb;
rb = do_stuff(rb);
...
rb do_stuff (really_big thing) // pass by value, return by value
{
thing->something = ...;
...
return thing;
}
This makes a copy of rb called thing. It is placed on the stack, wasting lots of memory and needlessly increasing the stack space used, increasing the possibility of stack overflow. And copying the contents from rb to thing takes lots of execution time. Then when it is returned, you make yet another copy, from thing back to rb.
By passing a pointer to the struct, none of the copying takes place, but the end result is the very same:
void do_stuff (really_big* thing)
{
thing->something = ...;
}
In open source component, cjson,
#define is_error(ptr) ((unsigned long)ptr > (unsigned long)-4000L)
Above statement is used to check the validity of pointer as shown below
json_object* reply = json_object_new_object();
if (!reply || is_error(reply))
{
. . . //error handling
}
How does comparing pointer with (unsigned long)-4000L validates pointer?
The reason for this looks like they're using the pointer value to contain "either a pointer or an error value".
Look here:
struct json_object* json_tokener_parse(const char *str)
{
struct json_tokener* tok;
struct json_object* obj;
tok = json_tokener_new();
obj = json_tokener_parse_ex(tok, str, -1);
if(tok->err != json_tokener_success)
obj = error_ptr(-tok->err); // <<<<<---
json_tokener_free(tok);
return obj;
}
The function is returning a special value as a pointer. The err_ptr macro returns the negative of the error code, presumably because the author assumes this will never be a valid pointer address.
Here is a test that demonstrates the expected usage of the macro, i.e. malformed JSON.
new_obj = json_tokener_parse("{ foo }");
if(is_error(new_obj)) printf("got error as expected\n");
So, the reason for using that special value is so they can hold "either a pointer to a structure or an error code". This could also be done with a union or a struct, or by some other means, but they chose to do it this way.
wrong check! There should not be any such value like (unsigned long)-4000L). It should be either a NULL (not allocated) or non-NULL (having valid value). Whenever the pointer gets deallocated, it should be reverted back to NULL, I mean re-assign to NULL to avoid dangling pointer. A value of non-NULL check is enough to know the pointer is valid and pointing to some valid content.
It doesn't, except in some very specific cases - maybe the original author had a pointer bug where his pointers were corrupted in a way that they got in the "range" of this comparison, or his compiler and operating system have some strange non-standard pointer validation or interpretation "features".
-4000 interpreted as an unsigned 32-bit integer is 0xfffff060.
If it were code running in kernel, it mighy have something to do with the userland / kernel memory space divide (i.e. top half vs bottom half of the address space), but even then it would probably be wrong. My money is on the first idea.
It look likes the author is making platform-specific assumptions about where virtual memory will be allocated. In this case the assumption is that a valid pointer will always be in within roughtly the first 4GB of addressable space [edit: that's onthe (dubious) assumption that long is 32-bit.]
Your particular example seems to come from a thing called OpenWebOS. I don't know what that is; but if they are the makers of the Operating System, then they get to make up their own rules about where the pointers will go. Perhaps that OS even has a convention that addresses above a certain value are used to signal errors.
If you want to write portable code, you should think hard before trying tricks like this.
I just want to know what below function is doing
static int myfunc(int val)
{
return *(volatile int *)val;
}
If val is a pointer when you pass it to this function, it makes sure that the value pointed by this pointer is read and returned to the caller.
I suspect this might be a trick for embedded devices, where sometimes the operation of reading a value at an address has some effect on the hardware.
For instance, reading from an hardware FIFO will pop the read value from the FIFO.
Marking here the pointer as volatile make the compiler not optimize the read if it detects that the value is not used.
Example:
#define FIFO_ADDRESS 0x800050
static int myfunc(int val)
{
return *(volatile int *)val; // the address *will* be read
}
static int bad( int val )
{
return *(int*)val; // might be optimized to nop()
// by the compiler if the value
// is not used by the caller
}
int main(){
bad( FIFO_ADDRESS ); // could be NOP since return value is not used
myfunc( FIFO_ADDRESS ); // *WILL* perform a READ operation on the FIFO,
// even though the result is not used, because
// of the volatile keyword
}
Note that I would do it differently, probably with a smartly named macro:
#define FORCE_INT_PTR_READ( address ) *(volatile int *)address
Could you give us an example of usage in your case?
It appears to be trying to confuse the optimiser (and possibly the user). It is taking an integer, treating it as a pointer to an integer, and dereferencing it. The 'volatile' ensures that the optimiser will generate code for that dereference at that point and won't let the optimiser omit the fetch from memory. This is usually used for accessing memory mapped hardware registers,
It does the following:
Passes a signed integer to a function.
Converts the contents of the signed integer to a pointer. This doesn't make sense, since pointers cannot be signed. Formally, this is also not well-defined behavior and anything can happen.
The volatile keyword suggests that the contents of val should equal to a physical hardware address. When reading from such addresses, the volatile keyword is necessary, since the hardware register's contents may change at any time.
It takes the contents of that address and treats it as int, which is then returned.
static means that the function has local scope.
Please note that if the target OS uses virtual addressing (such as a PC), the OS will just give you a slap on the fingers should you attempt to run this code.
All in all, this is poorly written code, which is neither safe, well-defined nor portable. You won't gain any valuable knowledge by staring at it.
It casts val to a pointer and returns it's value. Calls to myfunc() will work only if thy look like
int i, j;
i = 10;
j = myfunc( (int)&i )`
That should set j to 10
BUT it won't work on 64bit systems where sizeof(int *) is 8 and thus larger then sizeof(int) or on some old systems with sizeof(int) == 2
I am trying to understand a portion of code. I am leaving out a lot of the code in order to make it simpler to explain, and to avoid unnecessary confusion.
typedef void *UP_T;
void FunctionC(void *pvD, int Offset) {
unsigned long long int temp;
void *pvFD = NULL;
pvFD = pvD + Offset;
temp = (unsigned long long int)*(int *)pvFD;
}
void FunctionB(UP_T s) {
FunctionC(s, 8);
}
void FunctionA() {
char *tempstorage=(char *)malloc(0);
FunctionB(tempstorage);
}
int main () {
FunctionA();
return 0;
}
Like I said, I am leaving out a ton of code, hence the functions that appear useless because they only have two lines of code.
What is temp? That is what is confusing me. When I run something similar to this code, and use printf() statements along the way, I get a random number for pvD, and pvFD is that random number plus eight.
But, I could also be printing the values incorrectly (using %llu instead of %d, or something like that). I am pretty sure it's a pointer to the location in memory of tempstorage plus 8. Is this correct? I just want to be certain before I continue under that assumption.
The standard specifies that malloc(0) returns either NULL or a valid pointer, but that pointer is never to be dereferenced. There aren't any constraints regarding the actual implementation, so you can't rely on the returned pointer being another plus 8.
It's random in the sense that malloc is typically non-deterministic (i.e. gives different results from run to run).
The result of malloc(0) is implementation-defined (but perfectly valid), you just shouldn't ever dereference it. Nor should you attempt to do arithmetic on it (but this is generally true; you shouldn't use arithmetic to create pointers beyond the bounds of the allocated memory). However, calling free on it is still fine.
I have a C application that I've created in VS2008. I am creating a mock creation function that overrides function references in a struct. However if I try and do this in a straight forward fashion with something like:
void *ptr = &(*env)->GetVersion;
*ptr = <address of new function>
then I get a "error C2100: illegal indirection" error as *ptr, when ptr is a void * seems to be a banned construct. I can get around it by using a int/long pointer as well, mapping that to the same address and modifying the contents of the long pointer:
*structOffsetPointer = &(*env)->GetVersion;
functionPointer = thisGetVersion;
structOffsetPointerAsLong = (long *)structOffsetPointer;
*structOffsetPointerAsLong = (long)functionPointer;
but I am concerned that using long or int pointers will cause problems if I switch between 32 and 64 bit environments.
So is there are easy way to disable this error? Assuming not, is either int or long 64 bits under win64?
Then how about:
void **ptr = (void **) &(*env)->GetVersion;
*ptr = <address of new function>
The right way to do this is to work with the type system, avoid all the casting and declare actual pointers to functions like:
typedef int (*fncPtr)(void);
fncPtr *ptr = &(*env)->GetVersion;
*ptr = NewFunction;
The above assumes GetVersion is of type fncPtr and NewFunction is declared as
int NewFunction(void);
When dereferencing a "void *", you are left with a "void" which is has no size (or really no type for that matter), so it doesn't know how to assign something to it. It is the same as:
void blah = 0xdeadbabe; // let's assume a 32-bit addressing system
To add to my own response and give a solution, I would give it the proper type of a pointer to a function of the type GetVersion is. If GetVersion that your "env" struct field is pointing to is:
int GetVersion();
then you want:
int (**ptr)() = &(*env)->GetVersion;
Last time I played with void* & C under visual studio, VS didn't play nicely.
Here are some information datapoints:
A pointer is always the size of the system word(8/16/32/64)...(unless you have segmented memory, which I'm assuming you don't have). This is because it needs to point to anywhere in the memory space. For a von Neumann machine, a function pointer is going to be the same size as a data pointer, because data and code occupy the same memory space. This is not guaranteed under a Harvard architecture. I'm not familiar enough with Windows Vista to know if it programatically fakes out a Harvard architecture for security reasons.
I personally would not disable this error, just for the sake of letting the compiler do its job.
As mentioned, to store the address of a function in a pointer you should simply not do the indirection.
However, you also talk about being worried about the size of an int type that you might store a pointer into (which generally is not something you want to do unless you have a really good reason to).
If you want to hold a pointer in an int type for some reason, then on Windows a UINT_PTR type (or uintptr_t from stdint.h if you have it) will hold most pointer types (I don't think it's necessarily large enough to hold some pointer-to-member types).