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.
Related
We have two simple function.
#include <stdio.h>
/* first approach */
int power1(int *ptr)
{
return *ptr * *ptr;
}
/* second approach */
int power2(int *ptr)
{
int tmp = *ptr;
return tmp*tmp;
}
int main()
{
int val = 5;
printf("%d\n", power1(&val));
printf("%d\n", power2(&val));
return 0;
}
Which one is better? power1 is a little bit faster, but I have heard that power2 is more safety. I do not remember why? As far as I remember there is one case when power1(first approach) has bottleneck. Could you explain it? Does safety critical systems use second approach?
None is good. You want this:
#include <stdio.h>
/* second approach */
int power(int operand)
{
return operand*operand;
}
int main(void)
{
int val = 5;
printf("%d\n", power(val));
}
Now concerning your two approaches:
power2 is in no way "safer" than power1.
BTW:
A correct way to declare main is int main(void) and the return 0; at the end of main is not necessary, if main doesn't containt a return statement, there is an implicit return 0; at the end of main.
Which one is better?
They are equally good/bad
power1 is a little bit faster
If you compile without any optimization then "yes, power1 may be a little faster" but as soon as you turn on compiler optimization, they will (for any decent compiler) be equal.
but I have heard that power2 is more safety
That's wrong. Using the variables from the argument list is just as safe as using local variables.
Does safety critical systems use second approach?
No reason for doing that. However, use of pointers are banned in some safety critical systems. In you particular case it would be better to pass the integer directly instead of passing a pointer.
Another thing related to "safety" is integer overflow. Your code doesn't protect against integer overflow and integer overflow is undefined behavior. So that could be something to consider for safety critical systems.
I wish I knew what "safety" is supposed to mean here (I saw your comment that you got this from an interview, and that the interviewer did not explain what he meant by that).
There are only 4 reasons why a function should receive a pointer as a parameter:
The function is meant to update the parameter;
The parameter is an array expression, which is automatically converted to a pointer expression when passed as a function argument;
The parameter is a very large struct or similar aggregate type, and creating a local copy is deemed too expensive;
The parameter was created via malloc, calloc, or realloc.
None of these should apply to the snippets you posted. The "safest" option for them is to not use a pointer at all.
One "unsafe" aspect of using a pointer is that you may intend for the input to be read-only, but because you've been passed a pointer, you are able to modify the input. For those cases, you want to const-qualify that parameter:
void foo ( const char *str ) // we cannot modify what str points to
{
...
}
Another "unsafe" aspect of using a pointer is accidentally (or deliberately) updating the pointer value itself to access memory you shouldn't:
while ( *ptr )
do_something_with( ptr++ );
You can mitigate against this by declaring the pointer as const:
void bar( int * const ptr ) // we cannot update the value in ptr
This doesn't stop you from using the [] subscript operator, though:
while( ptr[i] )
do_something_with( ptr[i++] );
Now, if your interviewer was thinking of multiple threads or some machine-level issue with respect to interrupts or volatility, then maybe he has a point - if there's something that that can modify the thing ptr points to outside of the current thread of execution's control, then yes, the second method is "safer" in that respect (the pointed-to value won't change in the middle of the computation).
However, if the code is multithreaded and ptr can be modified in different threads, access to it should be synchronized via a mutex or something. If ptr can be updated outside of your program's control, it should have been declared volatile:
int power1( volatile int *ptr ) { ... }
int power2( volatile int *ptr ) { ... }
In power1 there will dereferencing 2 times - there will be 2 memory look ups related to dereferencing.
In power2 There will be dereferencing, but only once. Only in the statement int tmp = *ptr;.
So, power1 might be inefficient if looking this way in terms of speed.
This is based on assumption if you have compiler optimisations turned off.
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 = ...;
}
int main() {
int n;
long u=0,d=0,count=0,i=0;
char *p=(char *)malloc(sizeof(char)*n);
scanf("%ld",&n);
scanf("%s",p);
for(i=0;i<n;i++){
if(p[i]=='U'){
u=u+1;
}
if(p[i]=='D'){
d=d+1;
}
if((d-u)==0 && p[i]=='U'){
count=count+1;}
}
printf("%ld",count);
return 0;
}
In this standard syntax for implicit memory allocation, if i replace "int n;" with "long int n;"
An error pops up saying:
GDB trace:
Reading symbols from solution...done.
[New LWP 10056]
Core was generated by `solution'.
Program terminated with signal SIGSEGV, Segmentation fault.
I have searched everywhere for a solution, rather i quite dont know what to search for,
i would be greatful if anyone helps me out. Thanks :)
(This was executed on an online compiler)
There are a couple of things that I would like to point out:
First of all, you do not have to declare n as "long int". "long int" and "long" are the same. So,
long int n; //is same as
long n;
malloc() works perfectly fine whether n is an "int" or a "long". However, you don't seem to have initialized n. What is the value of n? C does not perform auto-initialization of variables and n might have a garbage value (even negative) which might cause your program to crash. So please give a value to n.
long n = 10; //example
or use a scanf() to input a value.
Now in your code, what is scanf() doing "after" malloc? I presume that you intended to read a value for n and then pass it to malloc. So please change the order of code to this:
scanf("%ld",&n);
char *p=(char *)malloc(sizeof(char)*n);
I ran your program with these changes on my system and it works fine (no segmentation fault)
malloc() limits: We know that malloc allocates from a heap. But I really don't see malloc returning NULL on current platforms (which are generally 64 bit). However, if you do try to allocate a very large chunk of memory, malloc might return NULL which will cause your program to crash.
So it's good to check the return value for malloc() and if that's NULL then take appropriate actions (such as retry or exit the program)
Having a check like the one below will always help:
if (p == NULL) {
printf("Malloc error");
exit(1);
}
Extracting the relevant parts of your code:
int n;
char *p=(char *)malloc(sizeof(char)*n);
The parameter to malloc is of type size_t, which is an unsigned type. If you pass an argument of any other integer type, it will be implicitly converted to size_t.
You report that with int n; you don't see a problem, but with long int n; your program dies with a segmentation fault.
In either case, you're passing an uninitialized value to malloc(). Just referring to the value of an uninitialized object has undefined behavior.
It may be that the arbitrary long int value you're passing to malloc() happens to cause it to fail and return a null pointer, causing a segmentation fault later when you try to dereference the pointer; the arbitrary int value might just happen to cause malloc to succeed. Checking whether malloc succeeded or failed would likely avoid the segmentation fault.
Passing an uninitialized value to malloc() is a completely useless thing to do. The fact that it behaves differently depending on whether that uninitialized value is an int or a long int is not particularly significant.
If you're curious, you might add a line to print the value of n before calling malloc(), and you definitely should check whether malloc() reported failure by returning a null pointer. Beyond that, you know the code is incorrect. Don't waste too much time figuring out the details of how it fails (or, worse, why it sometimes doesn't fail). Just fix the code by initializing n to the number of bytes you actually want to allocate. (And define n as an object of type size_t.)
Some more points:
The code in your question is missing several required #include directives. If they're missing in your actual code, you should add them. If they're present in your actual code, you should have included them in your question. Don't make assumptions about what you can safely leave out.
int main() should be int main(void). (This is a minor point that probably doesn't make any practical difference.)
scanf("%s",p);
This is inherently dangerous. It reads a blank-delimited string that can be arbitrarily long. If the user enters more characters than the buffer p points to can hold, you have undefined behavior.
u=u+1;
Not incorrect, but more idiomatically written as u ++;.
(d-u)==0 is more clearly and safely written as d == u. (For extreme values of d and u the subtraction can overflow; an equality comparison doesn't have that problem.)
Code:
union foo
{
char c;
int i;
};
void func(void * src)
{
union foo dest;
memcpy(&dest, src, sizeof(union foo)); //here
}
If I call func() like this:
int main()
{
char c;
int i;
func(&c);
func(&i);
return 0;
}
In the call func(&c), the size of c is less than sizeof(union foo), which may be dangerous, right?
Is the line with memcpy correct? And if not, how to fix it?
What I want is a safe call to memcpy that copy a void * pointer to a union.
A little background: this is extracted from a very complicated function, and the signature of func() including the void * parameter is out of my control. Of course the example does nothing useful, that's because I removed all the code that isn't relevant to provide an example with minimum code.
In the call func(&c), the size of c is less than sizeof(union foo), which may be dangerous, right?
Right, this will lead to undefined behaviour. dest will likely contain some bytes from memory areas surrounding c, and which these are depends on the internal workings of the compiler. Of course, as long as you only access dest.c, that shouldn't cause any problems in most cases.
But let me be more specific. According to the C standard, writing dest.c but reading dest.i will always yield undefined behaviour. But most compilers on most platforms will have some well-defined behaviour for those cases as well. So often writing dest.c but reading dest.i makes sense despite what the standard says. In this case, however, reading from dest.i will still be affected by unknown surrounding variables, so it is undefined not only from the standards point of view, but also in a very practical sense.
There also is a rare scenario you should consider: c might be located at the very end of allocated memory pages. (This refers to memory pages allocated from the operating system and eventually the memory management unit (MMU) hardware, not to the block-wise user space allocation done by malloc and friends.) In this case, reading more than that single byte might cause access to unmapped memory, and hence cause a severe error, most likely a program crash. Given the location of your c as an automatic variable in main, this seems unlikely, but I take it that this code snippet is only an example.
Is the line with memcpy correct? And if not, how to fix it?
Depends on what you want to do. As it stands, the code doesn't make too much sense, so I don't know what correct reasonable application you might have in mind. Perhaps you should pass the sizeof the src object to func.
Is the line with memcpy correct? And if not, how to fix it?
you should pass the size of memory pointed by void pointer so you can know src has this much size so you just need to copy this much of data...
Further more to be safe you should calculate the size of destination and based on that you should pass size so illegal access in reading and writing both can be avoided.
The memcpy is fine. By passing the address of the smallest member of the union, you will end with garbage in the larger member. A way to avoid the garbage-bit is to by default make all calls to func - which I assume you do control - use only pointers to the larger member - this can be achieved by setting the larger member to the smaller one: i = c and then call func(&i).
func itself is ok.
The problems lies in whether the caller really makes sure that the memory referenced when calling func() is at least sizeof(union foo).
If the latter is always the case, everything is fine. It is not then case for the two calls to func() in the OP's example.
If the memory referenced when calling func() is less then sizeof(union foo) then memcpy() provokes undefined behaviour.
Since you know what and what size to copy, why not give a more explicit function, let the function know how to copy the right size of memory which void pointer pointed to.
union foo
{
char c;
int i;
};
void func(void * src, const char * type)
{
union foo dest;
if(strcmp(type, "char") == 0){
memcpy(&dest, src, 1);
}else if(...){
}
}
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);