I use *ptr to iterate a char array from end to beginning (one byte at the time) and set some values in the way. When the pointer points to the first address the algorithm should stop.
char *buf = (char*)malloc(sizeof(char) * 3 + 1);
char *ptr = &buf[sizeof buf - 1]; // *ptr point to the last address
*ptr = '\0';
do {
if(alfa) {
*(--ptr) = "teststring"[alfa]; // *ptr decreases value by one
alfa -= i;
} else { *(--ptr) = 'N'; }
} while(*ptr != &buf[0]); // should check if *ptr is now pointing to the start of buf. If that's the case, stop.
But, after it check the addresses are equal, it gives me:
** stack smashing detected **: <unknown> terminated
Aborted (core dumped)
Another (and maybe relatable) thing is: malloc should allocate 4 bytes from memory, but when I check sizeof(buf) it has 8 bytes(?).
Note: The output of sizeof(char) * 3 + 1 is indeed 4. But it's not the same as sizeof(buf).
sizeof some_variable evaluates to the size of a variable.
So this sizeof buf evaluates to the size of buf. With buf being a pointer it gives you either 4 or 8 depending whether the code is compiled on a 32 or 64 bit platform.
To fix your problem change this
char *buf = (char*)malloc(sizeof(char) * 3 + 1);
char *ptr = &buf[sizeof buf - 1];
to this
size_t size = sizeof(char) * 3 + 1;
char *buf = malloc(size); /* No need to cast void-pointer sin C. */
char *ptr = &buf[size - 1]; // *ptr point to the last address
Taking into account that sizeof (char) equals 1 by definition just do:
size_t size = 3 + 1;
char *buf = malloc(size);
char *ptr = &buf[size - 1];
The first answer is right, but also, your last test:
while(*ptr != &buf[0]);
Isn't checking that ptr is not at the first position in the buffer. That would be ptr != &buf[0] or just ptr != buf.
You are seeing if the data at pointer (*ptr) is unequal to the the location of the beginning of the buffer, thereby comparing a char to a pointer. Your compiler is probably giving you a warning about it. Don't ignore warnings in C.
Related
Question : https://leetcode.com/problems/find-and-replace-in-string/
"""
char * findReplaceString(char * s, int* indices, int indicesSize, char ** sources, int
sourcesSize, char ** targets, int targetsSize){
int len = strlen(s);
char *copyS;
char *copy = (char*) malloc(sizeof(char)*len);
memcpy(copy, s, sizeof(char)*len);
copyS = copy;
int x = indicesSize-1;
int indexArr[1001] = {0};
int y;
for(int j=0; j<indicesSize; j++)
{
indexArr[indices[j]] = j;
}
qsort(indices, indicesSize, sizeof(int), cmp);
while((x >= 0))
{
y = indexArr[indices[x]];
copy = copyS+(indices[x]);
if(!(strncmp(copy, sources[y], strlen(sources[y]))))
{
copy = (char *)realloc(copy, sizeof(char)*(sizeof(copy) + sizeof(targets[y])));
strcpy(copy, targets[y]);
}
x--;
}
return copyS;
}
I am getting a runtime error due to the use of realloc. I was trying to modify the input string 's'. Got a runtime error due to realloc: Trying to free memory that was not malloced.
So I malloced new string pointer , *copy. Still getting same error when I use realloc on copy
There are several problems with the code.
For starters it is unclear whether the dynamically allocated array pointed to by the pointer copy shall contain a string or not.
If it shall contain a string then instead of
char *copy = (char*) malloc(sizeof(char)*len);
memcpy(copy, s, sizeof(char)*len);
you need to write
char *copy = (char*) malloc(sizeof(char)*( len + 1 ));
memcpy(copy, s, sizeof(char)*( len + 1 ));
Also it is unclear why there is used the magic number 1001 in this declaration
int indexArr[1001] = {0};
The pointer copyS was assigned with the address of the initially allocated memory
char *copyS;
char *copy = (char*) malloc(sizeof(char)*len);
memcpy(copy, s, sizeof(char)*len);
copyS = copy;
but then you are trying to reallocate the memory
copy = (char *)realloc(copy, sizeof(char)*(sizeof(copy) + sizeof(targets[y])));
As a result the pointer copyS can have an invalid value. And this pointer with an invalid value is returned from the function
return copyS
In turn the pointer copy is changed within the while loop
while((x >= 0))
{
y = indexArr[indices[x]];
copy = copyS+(indices[x]);
//..
So after such an assignment it does not point to the previously allocated memory extent. Hence using the pointer in the call of realloc
copy = (char *)realloc(copy, sizeof(char)*(sizeof(copy) + sizeof(targets[y])));
invokes undefined behavior.
And again this statement
copy = copyS+(indices[x]);
also invokes undefined behavior because after the memory reallocation the pointer copyS can be invalid.
Once you do this
copy = copyS+(indices[x]);
you can no longer use 'copy' as an argument to realloc or free. The pointer you pass to these functions must be the value returned by a prior malloc or realloc (or calloc)
Save the original 'copy' in a variable like 'originalCopy'
I have allocated an array of chars and I want to add another char at the beginning of the array while maintaining the order.
Ex. If pointer points to the beginning of 4 char blocks: A,B,C,D -> pointer[0]==A . If I add E the block of memory should look: E,A,B,C,D -> pointer[0]==E.
Additionally I want to do it in one line, without manually copying elements to another block and erasing the first. All functions have to be from C standard library.
I have though of something like pointer = realloc(pointer-1, (n-1)*size), but I'm not guaranteed that pointer-1 is free.
Thankful for your answers in advance
Adding space before the memory block rather than after it using realloc
Re-allocate with realloc() and then shift the data with memove().
I want to do it in one line,
Either use a helper function like below or employ a long hard to read un-maintainable line.
char *realloc_one_more_in_front(char *ptr, size_t current_size) {
void *new_ptr = realloc(ptr, sizeof *ptr * (current_size + 1));
if (new_ptr == NULL) {
return NULL; // Failure to re-allocate.
}
ptr = new_ptr;
memmove(ptr + 1, ptr, sizeof *ptr * current_size);
return ptr;
}
Sample usage. For simplicity of example, error handling omitted.
size_t current_size = 4;
char *ptr = malloc(current_size);
for (size_t i = 0 ; i<current_size; i++) {
ptr[i] = 'A' + i;
}
ptr = realloc_one_more_in_front(ptr, current_size++);
ptr[0] = 'E';
printf("%.*s\n", (int) current_size, ptr);
I'm testing the code below, but the output just says
ptr char = (null)
Any clue why this is happening?
int buf[1024];
buf[0] = 10;
buf[1] = 0;
buf[2] = 1992;
buf[3] = 42;
buf[4] = 5;
char *ptr;
ptr = (char*)buf+2;
printf("ptr char = %s\n",*ptr);
I just experimented on the above code so that I could know part by part what the code below would do.
here is the code I'm working on
int fillNSendHttpReq(int8u seq, char* domain, char* uri, char method, char* contentType, char* otherHeader, int contentLen, char* content, unsigned char timeout, char moreData, char isHttps)
{
int16u encodedLen = moreData?contentLen|0x8000:contentLen;
//if moredata = true then encodelen = contentlenBITWISEOR0x8000
char *ptr = NULL;
int8u buf[1024];
memset(buf, 0, sizeof(buf));
buf[0] = SNIC_HTTP_REQ;
buf[1] = seq;
*((int16u*)&buf[2]) = 0x5000; //swapped
buf[4] = method;
buf[5] = timeout;
if (isHttps) {
buf[0] = SNIC_HTTPS_REQ;//SNIC_HTTPS_REQ = 0
*((int16u*)&buf[2]) = 0xbb01; // 443 swapped
}
ptr = (char*)buf+6; //convert in8u to char * ???
ptr += sprintf(ptr, "%s", domain)+1; //ptr = ptr + strlen(domain)+1
ptr += sprintf(ptr, "%s", uri)+1;
ptr += sprintf(ptr, "%s", contentType)+1;
ptr += sprintf(ptr, "%s", otherHeader)+1;
*((int16u*)ptr) = swap16(encodedLen);
ptr += 2;
if (contentLen)
memcpy(ptr, content, contentLen);
serial_transmit(CMD_ID_SNIC, buf, ptr-(char*)buf+contentLen, ACK_NOT_REQUIRED);
return 0;
the part I don't understand is that ptr-(char*)buf+contentLenwas assigned to the variable defined as int and so that got me confused on where my content went which was a char.
int is of some size. When you add 2 to a char*, the pointer advances by two bytes; to advance it by the size of an int, you’d do (char*)(buf + 2). Two bytes past buf might be buf[1], or it might be half of buf[0], but apparently it points to zero, because that’s what you get by dereferencing ptr later – NULL is 0. When passing a string to printf, you don’t dereference it first.
I don’t really know how to fix that part, though, because it just doesn’t make a lot of sense. If your code is close to your intent, then this is probably what it should be:
char *ptr = (char*)(buf + 2);
printf("ptr char = %s\n", ptr);
in which case it’ll print either zero or one characters with your example buf.
char *ptr;
ptr = (char*)buf+2;
printf("ptr char = %s\n",*ptr);
ptr is a char pointer, so *ptr is the character it points to. You passed a character as parameter while the printf is waiting for a "string" (char pointer) so it crashed
Previously you have assigned ptr = (char*)buf+2; so ptr is now pointing to halfway between buff[0] and buff[1], and *ptr == 0 (since buf[0] = 10;, the third byte in buff is zero regardless of endianness, assuming sizeof(int) >= 4), so it represents a NULL value when printf reads it as a pointer. That's why you see the output
Use this
printf("ptr char = %s\n", ptr);
But then you'll see another empty output since ptr[0] is now '\0'
Why does this return no warnings? What is supposed to be wrong with the code?
char *str = malloc(strlen("hello" + 1));
strcpy(str, "hello");
Thanks!
Why would you expect warnings?
The code is broken because you should be doing strlen("hello") + 1, not strlen("hello" + 1) (which is equivalent to strlen("ello")).
This
char *str = malloc(strlen("hello" + 1));
strcpy(str, "hello");
is nearly equivalent to:
char *temp = "hello";
char *temp2 = temp + 1;
char *str = malloc(strlen(temp2));
strcpy(str, "hello");
so temp + 1 is pointer math (it returns a pointer to ello, and strcpy doesn't check if enough memory is present at destination ("standard" memory corruption caused by faulty code in C)
The end result is that strlen returns 4, strcpy uses 6 bytes of memory and a random piece of heap is trashed.
The below statement is incorrect.
char *str = malloc(strlen("hello" + 1));
It should be
char *str = malloc(strlen("hello") + 1);
strlen in this case would probably return you a value of 4 instead of 5 and strcpy will lead to Out of Bounds write. Execute the program with a memory analyzer and it shall point out an error to you.
I am having trouble understanding how to assign memory
to a double pointer.
I want to read an array of strings and store it.
char **ptr;
fp = fopen("file.txt","r");
ptr = (char**)malloc(sizeof(char*)*50);
for(int i=0; i<20; i++)
{
ptr[i] = (char*)malloc(sizeof(char)*50);
fgets(ptr[i],50,fp);
}
instead of this I just assign a large block of memory and
store the string
char **ptr;
ptr = (char**)malloc(sizeof(char)*50*50);
would that be wrong? And if so why is it?
Your second example is wrong because each memory location conceptually would not hold a char* but rather a char. If you slightly change your thinking, it can help with this:
char *x; // Memory locations pointed to by x contain 'char'
char **y; // Memory locations pointed to by y contain 'char*'
x = (char*)malloc(sizeof(char) * 100); // 100 'char'
y = (char**)malloc(sizeof(char*) * 100); // 100 'char*'
// below is incorrect:
y = (char**)malloc(sizeof(char) * 50 * 50);
// 2500 'char' not 50 'char*' pointing to 50 'char'
Because of that, your first loop would be how you do in C an array of character arrays/pointers. Using a fixed block of memory for an array of character arrays is ok, but you would use a single char* rather than a char**, since you would not have any pointers in the memory, just chars.
char *x = calloc(50 * 50, sizeof(char));
for (ii = 0; ii < 50; ++ii) {
// Note that each string is just an OFFSET into the memory block
// You must be sensitive to this when using these 'strings'
char *str = &x[ii * 50];
}
char **ptr;
fp = fopen("file.txt","r");
ptr = (char**)malloc(sizeof(char*)*50);
for(int i=0; i<50; i++)
{
ptr[i] = (char*)malloc(sizeof(char)*50);
fgets(ptr[i],50,fp);
}
fclose(fp);
may be your typo mistake but your loop should be of 50 instead of 20 if you are looking for 50 x 50 matrix. Also after allocation of memory mentioned above you can access the buffer as ptr[i][j] i.e in the 2D format.
A double pointer is just a pointer to another pointer. So you can allocate it like this:
char *realptr=(char*)malloc(1234);
char **ptr=&realptr;
You have to keep in mind where your pointer is stored at (in this example the double pointer points to a pointer variable on the stack so it's invalid after the function returns).
i will give one example, which might clear of the doubt,
char **str; // here its kind a equivalent to char *argv[]
str = (char **)malloc(sizeof(char *)*2) // here 2 indicates 2 (char*)
str[0]=(char *)malloc(sizeof(char)*10) // here 10 indicates 10 (char)
str[1]=(char *)malloc(sizeof(char)*10) // <same as above>
strcpy(str[0],"abcdefghij"); // 10 length character
strcpy(str[1],"xyzlmnopqr"); // 10 length character
cout<<str[0]<<endl; // to print the string in case of c++
cout<<str[1]<<endl; // to print the string in case of c++
or
printf("%s",str[0]);
printf("%s",str[1]);
//finally most important thing, dont't forget to free the allocated mem
free(str[0]);
free(str[1]);
free(str);
other simpler way to memorize
Case -1 :
step-1 : char *p;
step -2 :
please read it like below
char (*p); ==> p is a pointer to a char
now you just need to do malloc for the type (step-2) without braces
i.e., p = malloc(sizeof(char) * some_len);
Case -2 :
step-1 : char **p;
step -2 :
please read it like below
char* (* p); ==> p is a pointer to a char *
now you just need to do malloc for the type (step-2) without braces
i.e., p = malloc(sizeof(char *) * some_len);
Case -3 :
No one uses this but just for sake of explanation
char ***p;
read it as,
char** (*p); ==> p is a pointer to a char** (and for this check case-2 above)
p = malloc(sizeof(char**) * some_len);
Adding to Pent's answer, as he correctly pointed out, you will not be able to use this double pointer once the function returns, because it will point to a memory location on the function's activation record on stack which is now obsolete (once the function has returned). If you want to use this double pointer after the function has returned, you may do this:
char * realptr = (char *) malloc(1234);
char ** ptr = (char **) malloc(sizeof(char *));
*ptr = realptr;
return ptr;
The return type of the function must obviously be char ** for this.
well, this is how I do it:
#include <stdlib.h>
int main(void)
{
int i = -1; // just a counter
int j = 5; // how many strings
char *s[j];
while(++i < j)
s[i] = malloc(sizeof(char*)); // allocating avery string separately
return (0);
}
this also works:
char **allocate(int lines)
{
int i = -1;
char **s = malloc(sizeof(char *) * lines); // allocating lines
while (++i < lines)
{
s[i] = malloc(sizeof(char*)); // alicating line
scanf("%s", s[i]);
}
return (s);
}
int main(int ac, char *av[])
{
int lines = 5; // how many lines
char **s = allocate(lines);
return (0);
}
Double pointer is, simply put, a pointer to a pointer,
In many cases it is used as an array of other types.
For example, if you want to create an array of strings you can simply do:
char** stringArray = calloc(10, 40);
this will create an array of size 10, each element will be a string of length 40.
thus you can access this by stringArray[5] and get a string in the 6th position.
this is one usage, the others are as mentioned above, a pointer to a pointer, and can be allocated simply by:
char* str = (char*)malloc(40);
char** pointerToPointer = &str //Get the address of the str pointer, valid only in the current closure.
read more here:
good array tutorial