What's a Singleton pointer in C? - c

I have some code which is like this (This is not production code. Just a sample code)
char *inbuf = NULL;
inbuf = buf; //buf is some other valid buffer of size 100.
func(&inbuf);
.....
void func(char **p)
{
...
(*p)++;
...
}
Coverity Tool says that "Taking address with &inbuf yields a singleton". I have heard the term singleton with respect to C++. But, what does a singleton pointer mean in terms of C?

What does a singleton pointer mean in terms of C?
In this case I think Coverity is referring to the difference between an array of char* and a pointer to a single char* created by taking the address of that array.
Coverity is warning you that by passing the address of the first element of buf to func, you're making it more difficult for yourself to safely write to that array because you can't easily determine its size.
It's difficult to be sure without seeing all of your code, but assuming buf is an array you've declared somewhere in your top-level function then using the sizeof operator on buf from that function will yield the size of the array.
However, when you pass the address of buf to func at the line
func(&inbuf);
...func merely receives a pointer to the first element of that array. From func you can no longer use sizeof to determine the size of the array - it will just return the size of the pointer - and so you can't safely write to that pointer without some implicit understanding of how much space the array contains.
This makes for fragile code, and hence is poor practice.
(None of this is anything to do with the Singleton Pattern)

The Coverity analysis is flagging a defect of the following pattern:
typeA var; // declare a variable to some type
func(&var) // call a function passing the address of var
func(typeA *var) {
...
var++; // inside the function do pointer arithmetic on var
This is a bug pattern, frequently, because the function expects a pointer to a buffer, but you're passing it a pointer to a singleton value. The type systems in C/C++ do not distinguish between "pointer to one object" and "pointer to array of objects".

Related

why is there NO 'l-value required' error while incrementing array name [duplicate]

This question already has answers here:
Difference between passing array and array pointer into function in C
(3 answers)
Closed 5 years ago.
As far as I know, you cannot modify a Array variable
How come this code run without any error.
Is there anything I am missing out here. (It's not about why there is 'L-VALUE REQUIRED' error , it's about why there isn't.)
#include<stdio.h>
int strlens(char *s);
void main(){
char s[]="get me length of this string ";
// s++ ; this would give 'L-VALUE REQUIRED ERROR'
printf("%d",strlens(s));
}
int strlens(char s[]){
int i;
for(i=0; *s!='\0';++i, ++s) ; //++s: there is NO 'L-VALUE REQUIRED ERROR'
return i;
}
A quirk of the C language that is well-known to seasoned C programmers, but trips up new C coders to no end, is that arrays are "pass by reference". Generally speaking, an array name used in most expressions will "decay" to the address of its first element. Functions carry that to an extreme case, where the array syntax in the function parameter is actually an alias for the pointer type itself.
This is described in paragraph 7 of c11's §6.7.6.3 Function declarators:
A declaration of a parameter as ‘‘array of type’’ shall be adjusted to ‘‘qualified pointer to
type’’, where the type qualifiers (if any) are those specified within the [ and ] of the
array type derivation.
Historically, this quirk was an attempt to maintain behavioral compatibility to C's predecessors, B and BCPL, and efficient structure layout. C's predecessor had a semantic for arrays in that its physical layout was actually a pointer that got dynamically allocated and initialized at runtime. When passed to a procedure, the pointer semantic was a natural adoption. Dennis Ritchie invented the notion of allowing the array syntax represent the actual address of the array, and then maintained the pointer semantic when passed to a function. Thus, the inventor of the C language considered this quirk a novel solution to a real world problem (semantic compatibility).
References:
The Development of the C Language
This line
char s[]="get me length of this string ";
defines a character array. s is not a pointer, it evaluates to an address (when fed to a pointer for instance, or when accessing a value like s[i] equivalent to *(s+i)), or represents the space occupied by the array (eg in sizeof(s))
But in a function signature like this
int strlens(char s[]){
char s[] is equivalent to char *s, and you can treat s like a pointer.
char arr[] = "asds"
Here, arr is just a name. It refers to a memory location but is not a pointer. The compiler substitutes the address directly wherever arr is used. It is not a pointer because unlike pointers, it does not have any space allocated to store an address. It is a mere compile time symbol. Hence, at run-time there is nothing on which you can do pointer arithmetic on. If you had to increment something, that something should exist at run-time.
More details:
Basically, the literal "asds" is stored in your executable and the compiler knows where exactly it is (well, the compiler is placing it in the executable, so it should know?).
The identifier arr is just a name to that location. As in, arr is not a pointer, i.e: it does not exist in memory storing an address.
void func(char arr[])
In case of a function argument, the arr does exist in memory at run-time because the arguments are pushed onto the call stack before making the function call. Since arrays are passed by reference, the address of the first element of the actual parameter is pushed onto the call stack.
Therefore, arr is allocated some space on the stack where it stores the address to the first element of your actual array.
Now you have a pointer. Hence you can increment (or do any pointer arithmetic on it).

Why is setting an array of characters to NULL illegal? Passing to function changes behavior

The name of an array is a synonym for the address of the first element of the array, so why can't this address be set to NULL? Is it a language rule to prevent a memory leak?
Also, when we pass an array to a function, it's behavior changes and it becomes possible to set it to NULL.
I don't understand why this occurs. I know it has something to do with pointers, but I just can't wrap my mind around it.
Example:
void some_function(char string[]);
int main()
{
char string[] = "Some string!";
some_function(string);
printf("%s\n", string);
return 0 ;
}
void some_function(char string[])
{
string = NULL;
}
Output: Some string!
I read that when an array is passed into a function, what's actually passed are pointers to each element, but wouldn't the name of the array itself still be a synonym for the address of the first element? Why is setting it to NULL here even allowed, but not in the main function?
Is it at all possible to set an array to NULL?
An array is not a pointer - the symbol string in your case has attributes of address and size whereas a pointer has only an address attribute. Because an array has an address it can be converted to or interpreted as a pointer, and the language supports this implicitly in a number of cases.
When interpreted as a pointer you should consider its type to be char* const - i.e. a constant pointer to variable data, so the address cannot be changed.
In the case of passing the array to a function, you have to understand that arrays are not first class data types in C, and that they are passed by reference (i.e. a pointer) - loosing the size information. The pointer passed to the function is not the array, but a pointer to the array - it is variable independent of the original array.
You can illustrate what is effectively happening without the added confusion of function call semantics by declaring:
char string[] = "Some string!";
char* pstring = string ;
then doing:
pstring = NULL ;
Critically, the original array data cannot just "disappear" while it is in scope (or at all if it were static), the content of the array is the variable, whereas a pointer is a variable that refers to data. A pointer implements indirection, and array does not. When an array is passed to a function, indirection occurs and a pointer to the array is passed rather than a copy of the array.
Incidentally, to pass an array (which is not a first class data type) by copy to a function, you must wrap int within a struct (structs in C are first class data types). This is largely down to the original design of C under constraints of systems with limited memory resources and the need to to maintain compatibility with early implementations and large bodies of legacy code.
So the fact that you cannot assign a pointer to an array is hardly the surprising part - because to do so makes little sense. What is surprising perhaps is the semantics of "passing an array" and the fact that an array is not a first class data type; leading perhaps to your confusion on the matter.
You can't rebind an array variable. An array is not a pointer. True, at a low level they are approximately similar, except pointers have no associated dimension / rank information.
You cant assign NULL to the actual array (same scope), but you can assign to a parameter since C treats it like a pointer.
The standard says:
7 A declaration of a parameter as ‘‘array of type’’ shall be adjusted
to ‘‘qualified pointer to type’’,
So in the function the NULL assignment is legal.

How does an array pointer store its size? [duplicate]

This question already has answers here:
Why isn't the size of an array parameter the same as within main?
(13 answers)
Closed 7 years ago.
#include "stdio.h"
#define COUNT(a) (sizeof(a) / sizeof(*(a)))
void test(int b[]) {
printf("2, count:%d\n", COUNT(b));
}
int main(void) {
int a[] = { 1,2,3 };
printf("1, count:%d\n", COUNT(a));
test(a);
return 0;
}
The result is obvious:
1, count:3
2, count:1
My questions:
Where is the length(count/size) info stored when "a" is declared?
Why is the length(count/size) info lost when "a" is passed to the test() function?
There's no such thing as "array pointer" in C language.
The size is not stored anywhere. a is not a pointer, a is an object of type int[3], which is a fact well known to the compiler at compile time. So, when you ask the compiler to calculate sizeof(a) / sizeof(*a) at compile time the compiler knows that the answer is 3.
When you pass your a to the function you are intentionally asking the compiler to convert array type to pointer type (since you declared the function parameter as a pointer). For pointers your sizeof expression produces a completely different result.
Where is the length(count/size) info stored when "a" is declared?
It's not stored anywhere. The sizeof operator (used in the COUNT() macro) returns the size of the entire array when it's given a true array as the operand (as it is in the first printf())
Why is the length(count/size) info lost when "a" is passed to the test() function?
Unfortunately, in C, array parameters to functions are a fiction. Arrays don't get passed to functions; the parameter is treated as a pointer, and the array argument passed in the function call gets 'decayed' into a simple pointer. The sizeof operator returns the size of the pointer, which has no correlation to the size of the array that was used as an argument.
As a side note, in C++ you can have a function parameter be a reference to an array, and in that case the full array type is made available to the function (i.e., the argument doesn't decay into a pointer and sizeof will return the size of the full array). However, in that case the argument must match the array type exactly (including the number of elements), which makes the technique mostly useful only with templates.
For example, the following C++ program will do what you expect:
#include "stdio.h"
#define COUNT(a) (sizeof(a) / sizeof(*(a)))
template <int T>
void test(int (&b)[T]) {
printf("2, count:%d\n", COUNT(b));
}
int main(int argc, char *argv[]) {
int a[] = { 1,2,3 };
printf("1, count:%d\n", COUNT(a));
test(a);
return 0;
}
Nowhere.
Because it wasn't stored in the first place.
When you refer to the array in main(), the actual array declaration definition is visible, so sizeof(a) gives the size of the array in bytes.
When you refer to the array in the function, the parameter is effectively 'void test(int *b), and the size of the pointer divided by the size of the thing it points at happens to be 1 on a 32-bit platform, whereas it would be 2 on a 64-bit platform with LP64 architecture (or, indeed, on an LLP64 platform like Windows-64) because pointers are 8 bytes and int is 4 bytes.
There isn't a universal way to determine the size of an array passed into a function; you have to pass it explicitly and manually.
From the comment:
I still have two questions:
What do you mean by "..the actual declaration is visible.."? [T]he compiler (or OS) could get the length info through sizeof(a) function?
Why the pointer &(a[0]) doesn't contain the length info as the pointer "a"?
I think you learned Java before you learned C, or some other more modern language. Ultimately, it comes down to "because that is the way C is defined". The OS is not involved; this is a purely compiler issue.
sizeof() is an operator, not a function. Unless you are dealing with a VLA (variable length array), it is evaluated at compile time and is a constant value.
Inside main(), the array definition (I misspoke when I said 'declaration') is there, and when the sizeof() operator is applied to the name of an actual array - as opposed to an array parameter to a function - then the size returned is the size of the array in bytes.
Because this is C and not Algol, Pascal, Java, C#, ...
C does not store the size of the array - period. That is a fact of life. And, when an array is passed to a function, the size information is not passed to the function; the array 'decays' to a pointer to the zeroth element of the array - and only that pointer is passed.
1. Where is the length(count/size) info stored when "a" is declared?
It isn't stored. The compiler knows what a is and therefore knows it's size. So the compiler can replace sizeof() with the actual size.
2. Why is the length(count/size) info lost when "a" is passed to the test() function?
In this case, b is declared as a pointer (even though it may point to a). Given a pointer, the compiler does not know the size of the data pointed to.
Array pointer does not store the size. However, the[] type is not actually a pointer. It's a different type. When you say int a[] = {1,2,3}; you define array of 3 elements, and since it is defined so, sizeof(a) gives you the size of the whole array.
When however you declare parameter as int a[], it's pretty much the same as int *a, and sizeof(a) would be the size of the pointer (which coincidentally may be the same as the size of int, but not always).
In C, there's no way to store the size in pointer type, so if you need the size, you'd have to pass it as additional argument or use struct.
Where is the length(count/size) info stored when "a" is declared?
Nowhere. The question doesn't make sense BTW.
Why is the length(count/size) info lost when "a" is passed to the test() function?
Array decays into pointer(to the first element) when passed to a function. So the answer is 'nowhere' and similar to the previous question this one again doesn't make any sense.

memcpy fails but assignment doesn't on character pointers

Actually, memcpy works just fine when I use pointers to characters, but stops working when I use pointers to pointers to characters.
Can somebody please help me understand why memcpy fails here, or better yet, how I could have figured it out myself. I am finding it very difficult to understand the problems arising in my c/c++ code.
char *pc = "abcd";
char **ppc = &pc;
char **ppc2 = &pc;
setStaticAndDynamicPointers(ppc, ppc2);
char c;
c = (*ppc)[1];
assert(c == 'b'); // assertion doesn't fail.
memcpy(&c,&(*ppc[1]),1);
if(c!='b')
puts("memcpy didn't work."); // this gets printed out.
c = (*ppc2)[3];
assert(c=='d'); // assertion doesn't fail.
memcpy(&c, &(*ppc2[3]), 1);
if(c != 'd')
puts("memcpy didn't work again.");
memcpy(&c, pc, 1);
assert(c == 'a'); // assertion doesn't fail, even though used memcpy
void setStaticAndDynamicPointers(char **charIn, char **charIn2)
{
// sets the first arg to a pointer to static memory.
// sets the second arg to a pointer to dynamic memory.
char stat[5];
memcpy(stat, "abcd", 5);
*charIn = stat;
char *dyn = new char[5];
memcpy(dyn, "abcd", 5);
*charIn2 = dyn;
}
your comment implies that char stat[5] should be static, but it isn't. As a result charIn points to a block that is allocated on the stack, and when you return from the function, it is out of scope. Did you mean static char stat[5]?
char stat[5];
is a stack variable which goes out of scope, it's not // sets the first arg to a pointer to static memory.. You need to malloc/new some memory that gets the abcd put into it. Like you do for charIn2
Just like what Preet said, I don't think the problem is with memcpy. In your function "setStaticAndDynamicPointers", you are setting a pointer to an automatic variable created on the stack of that function call. By the time the function exits, the memory pointed to by "stat" variable will no longer exist. As a result, the first argument **charIn will point to something that's non-existent. Perhaps you can read in greater detail about stack frame (or activation record) here: link text
You have effectively created a dangling pointer to a stack variable in that code. If you want to test copying values into a stack var, make sure it's created in the caller function, not within the called function.
In addition to the definition of 'stat', the main problem in my eyes is that *ppc[3] is not the same as (*ppc)[3]. What you want is the latter (the fourth character from the string pointed to by ppc), but in your memcpy()s you use the former, the first character of the fourth string in the "string array" ppc (obviously ppc is not an array of char*, but you force the compiler to treat it as such).
When debugging such problems, I usually find it helpful to print the memory addresses and contents involved.
Note that the parenthesis in the expressions in your assignment statements are in different locations from the parenthesis in the memcpy expressions. So its not too suprising that they do different things.
When dealing with pointers, you have to keep the following two points firmly in the front of your mind:
#1 The pointer itself is separate from the data it points to. The pointer is just a number. The number tells us where, in memory, we can find the beginning of some other chunk of data. A pointer can be used to access the data it points to, but we can also manipulate the value of the pointer itself. When we increase (or decrease) the value of the pointer itself, we are moving the "destination" of the pointer forward (or backward) from the spot it originally pointed to. This brings us to the second point...
#2 Every pointer variable has a type that indicates what kind of data is being pointed to. A char * points to a char; a int * points to an int; and so on. A pointer can even point to another pointer (char **). The type is important, because when the compiler applies arithmetic operations to a pointer value, it automatically accounts for the size of the data type being pointed to. This allows us to deal with arrays using simple pointer arithmetic:
int *ip = {1,2,3,4};
assert( *ip == 1 ); // true
ip += 2; // adds 4-bytes to the original value of ip
// (2*sizeof(int)) => (2*2) => (4 bytes)
assert(*ip == 3); // true
This works because the array is just a list of identical elements (in this case ints), laid out sequentially in a single contiguous block of memory. The pointer starts out pointing to the first element in the array. Pointer arithmetic then allows us to advance the pointer through the array, element-by-element. This works for pointers of any type (except arithmetic is not allowed on void *).
In fact, this is exactly how the compiler translates the use of the array indexer operator []. It is literally shorthand for a pointer addition with a dereference operator.
assert( ip[2] == *(ip+2) ); // true
So, How is all this related to your question?
Here's your setup...
char *pc = "abcd";
char **ppc = &pc;
char **ppc2 = &pc;
for now, I've simplified by removing the call to setStaticAndDynamicPointers. (There's a problem in that function too—so please see #Nim's answer, and my comment there, for additional details about the function).
char c;
c = (*ppc)[1];
assert(c == 'b'); // assertion doesn't fail.
This works, because (*ppc) says "give me whatever ppc points to". That's the equivalent of, ppc[0]. It's all perfectly valid.
memcpy(&c,&(*ppc[1]),1);
if(c!='b')
puts("memcpy didn't work."); // this gets printed out.
The problematic part —as others have pointed out— is &(*ppc[1]), which taken literally means "give me a pointer to whatever ppc[1] points to."
First of all, let's simplify... operator precedence says that: &(*ppc[1]) is the same as &*ppc[1]. Then & and * are inverses and cancel each other out. So &(*ppc[1]) simplifies to ppc[1].
Now, given the above discussion, we're now equipped to understand why this doesn't work: In short, we're treating ppc as though it points to an array of pointers, when in fact it only points to a single pointer.
When the compiler encounters ppc[1], it applies the pointer arithmetic described above, and comes up with a pointer to the memory that immediately follows the variable pc -- whatever that memory may contain. (The behavior here is always undefined).
So the problem isn't with memcopy() at all. Your call to memcpy(&c,&(*ppc[1]),1) is dutifully copying 1-byte (as requested) from the memory that's pointed to by the bogus pointer ppc[1], and writing it into the character variable c.
As others have pointed out, you can fix this by moving your parenthesis around:
memcpy(&c,&((*ppc)[1]),1)
I hope the explanation was helpful. Good luck!
Although the previous answers raise valid points, I think the other thing you need to look at is your operator precedence rules when you memcpy:
memcpy(&c, &(*ppc2[3]), 1);
What happens here? It might not be what you're intending. The array notation takes higher precedence than the dereference operator, so you first attempt perform pointer arithmetic equivalent to ppc2++. You then dereference that value and pass the address into memcpy. This is not the same as (*ppc2)[1]. The result on my machine is an access violation error (XP/VS2005), but in general this is undefined behaviour. However, if you dereference the same way you did previously:
memcpy(&c, &((*ppc2)[3]), 1);
Then that access violation goes away and I get proper results.

Pointer arithmetic and arrays: what's really legal?

Consider the following statements:
int *pFarr, *pVarr;
int farr[3] = {11,22,33};
int varr[3] = {7,8,9};
pFarr = &(farr[0]);
pVarr = varr;
At this stage, both pointers are pointing at the start of each respective array address. For *pFarr, we are presently looking at 11 and for *pVarr, 7.
Equally, if I request the contents of each array through *farr and *varr, i also get 11 and 7.
So far so good.
Now, let's try pFarr++ and pVarr++. Great. We're now looking at 22 and 8, as expected.
But now...
Trying to move up farr++ and varr++ ... and we get "wrong type of argument to increment".
Now, I recognize the difference between an array pointer and a regular pointer, but since their behaviour is similar, why this limitation?
This is further confusing to me when I also consider that in the same program I can call the following function in an ostensibly correct way and in another incorrect way, and I get the same behaviour, though in contrast to what happened in the code posted above!?
working_on_pointers ( pFarr, farr ); // calling with expected parameters
working_on_pointers ( farr, pFarr ); // calling with inverted parameters
.
void working_on_pointers ( int *pExpect, int aExpect[] ) {
printf("%i", *pExpect); // displays the contents of pExpect ok
printf("%i", *aExpect); // displays the contents of aExpect ok
pExpect++; // no warnings or errors
aExpect++; // no warnings or errors
printf("%i", *pExpect); // displays the next element or an overflow element (with no errors)
printf("%i", *aExpect); // displays the next element or an overflow element (with no errors)
}
Could someone help me to understand why array pointers and pointers behave in similar ways in some contexts, but different in others?
So many thanks.
EDIT: Noobs like myself could further benefit from this resource: http://www.panix.com/~elflord/cpp/gotchas/index.shtml
The difference is because for farr++ to have any effect, somewhere the compiler would need to store that farr will evaluate to the address of the second element of the array. But there is no place for that information. The compiler only allocates place for 3 integers.
Now when you declare that a function parameter is an array, the function parameter won't be an array. The function parameter will be a pointer. There are no array parameters in C. So the following two declarations are equivalent
void f(int *a);
void f(int a[]);
It doesn't even matter what number you put between the brackets - since the parameter really will be a pointer, the "size" is just ignored.
This is the same for functions - the following two are equivalent and have a function pointer as parameter:
void f(void (*p)());
void f(void p());
While you can call both a function pointer and a function (so they are used similar), you also won't be able to write to a function, because it's not a pointer - it merely converts to a pointer:
f = NULL; // error!
Much the same way you can't modify an array.
In C, you cannot assign to arrays. So, given:
T data[N];
where T is a type and N is a number, you cannot say:
data = ...;
Given the above, and that data++; is trying to assign to data, you get the error.
There is one simple rule in C about arrays and pointers. It is that, in value contexts, the name of an array is equivalent to a pointer to its first element, and in object contexts, the name of an array is equivalent to an array.
Object context is when you take the size of an array using sizeof, or when you take its address (&data), or at the time of initialization of an array. In all other contexts, you are in value context. This includes passing an array to a function.
So, your function:
void working_on_pointers ( int *pExpect, int aExpect[] ) {
is equivalent to
void working_on_pointers ( int *pExpect, int *aExpect ) {
The function can't tell if it was passed an array or a pointer, since all it sees is a pointer.
There are more details in the answers to the following questions:
type of an array,
sizeof behaving unexpectedly,
Also see this part of C for smarties website, which is very well-written.
Trying to increment farr or varr fails because neither one is a pointer. Each is an array. The name of an array, when evaluated by itself (except as the operand of the sizeof or address-of operator) evaluates to a value (an rvalue) that's of the correct type to be assigned to a pointer. Trying to increment it is a bit like trying to increment 17. You can increment an int that contains the value 17, but incrementing 17 itself won't work. The name of an array is pretty much like that.
As for your second part, it's pretty simple: if you attempt to declare a function parameter of array type, the compiler silently "adjusts" it to a pointer type. As such, in your working_on_pointers, aExpect and pExpect have exactly the same type. Despite the array-style notation, you've defined aExpect as having type 'pointer to int'. Since the two are the same, it's entirely expected that they'll act the same.
Have a look at this answer I posted in relation to differences between pointers and arrays here on SO.
Hope this helps.
okay, i may be wrong. but arrays and pointers can be used alternately.
int * ptr = (int *)malloc(2* sizeof(int));
ptr[0]=1;
ptr[1]=2;
printf ("%d\n", ptr[0]);
printf ("%d\n", ptr[1]);
here i declared a pointer and now i am treating it as array.
moreover:
As a consequence of this definition,
there is no apparent difference in the
behavior of the "array subscripting"
operator [] as it applies to arrays
and pointers. In an expression of the
form a[i], the array reference "a"
decays into a pointer, following the
rule above, and is then subscripted
just as would be a pointer variable in
the expression p[i] (although the
eventual memory accesses will be
different, as explained in question
2.2). In either case, the expression x[i] (where x is an array or a
pointer) is, by definition, identical
to *((x)+(i)).
reference: http://www.lysator.liu.se/c/c-faq/c-2.html
you need to understand the basic concept of arrays.
when you declare an array i.e
int farr[]
you are actually declaring a pointer with this declaration
const int * farr
i.e; a "constant" pointer to integer. so when you do farr++ you are actually trying to add up to a pointer which is constant, hence compilers gives you an error.
if you need to understand, try to declare a pointer with the above declaration and you would not be able to do the arithmetic which are legal on normal pointers.
P.S:
its been quiet a while i have coded in C so i am not sure about exact syntax. but bottom line is the difference between a pointer and a constant pointer.

Resources