Strncpy issue with Double Pointer Char Array - c

I can't seem to figure out what is wrong with my code below:
I have a double pointer char array, declared and initialized with the following:
unsigned char **buffer = (unsigned char**) malloc (num * sizeof(char*));
for ( i = 0; i < num; i++ )
{
buffer[i] = (unsigned char*) calloc(PACKETSIZE, sizeof(char));
}
Then I'm trying to copy a string to the middle section of one of the char* arrays, but it does not seem to work. I'm not sure whether my error was with the memory allocation or when I tried to copy. I know for a fact the source char* has content.
The code I'm trying to copy (Header is a struct, I want to write to the array after the memory address of Header for buffer[i], so I'm doing a bit of a pointer arithmetic).
strncpy ((unsigned char *)(buffer[i]+sizeof(Header)), buffer2, bytes_to_copy);
After the code runs, the buffer[i] stays empty.
Here is a sample of the Header struct:
typedef struct Head
{
unsigned int x;
unsigned int y;
} Header ;

Your allocation line:
buffer[i] = (unsigned char*) calloc(PACKETSIZE, sizeof(char));
will set all elements of buffer[i] to zero.
Then, your copy line:
strncpy ((unsigned char *)(buffer[i]+sizeof(Header)), buffer2, bytes_to_copy);
will only set the buffer[i] data that come after the first sizeof(Header) elements.
So, those first sizeof(Header) elements will be zero. Thus, any attempt to use a strxxx function to display that buffer will assume the string is empty (first byte is zero).

Related

Pointers to Pointers: What datatype with variable length strings?

I need to store a list of names in C. I decided a good way to do this would be to use double pointers (or pointers-to-pointers).
So I will have an array of names. Each array value is a pointer to another array: the name, stored as a character array.
The names might look like
unsigned char *name = "Joseph";
etc.
And then I would have a list of names (double pointer), to which I could (dynamically) assign each name (single pointer).
(type) **listOfNames;
My question is: what type should the double pointer be? Since it is a pointer to a pointer, I was thinking that it must be large enough to hold an arbitrary memory address: unsigned long, maybe? Or is there another type meant specifically for double pointers?
Alternatively — is there a better way of storing a variable-length array or variable-length strings?
If you have a collection of unsigned char * values:
unsigned char *name_0 = "Joseph";
unsigned char *name_1 = "Helen";
unsigned char *name_2 = "Maximillian";
Then you can create:
unsigned char *data[] = { name_0, name_1, name_2 };
unsigned char **listOfNames = data;
Note that you need to allocate space for the list of pointers — in my code, that's the data array. You could use malloc() instead, but you'd need to remember to code the matching free() at some point.
Adding appropriate const qualifications is left as an exercise in frustration to the interested reader.
If you are reading a variable length list of names from a file a run time, with (presumably) one name per line, then you'd do best with POSIX getline() and strdup().
There must be a number of other questions that deal with this scenario, so I'll be terse with this code:
char **read_file(FILE *fp)
{
char *buffer = 0;
size_t bufsiz = 0;
char **lines = 0;
size_t n_lines = 0;
size_t n_alloc = 0;
while (getline(&buffer, &bufsiz, fp) > 0)
{
if (n_lines + 1 >= n_alloc)
{
size_t new_num = (n_alloc + 1) * 2;
size_t new_size = new_num * sizeof(*lines);
char **new_lines = realloc(lines, new_size);
if (new_lines == 0)
{
free(buffer);
free(lines);
return(0);
}
lines = new_lines;
n_alloc = new_num;
}
lines[n_lines++] = strdup(buffer); // Includes newline!
}
lines[n_lines] = 0; // Null terminate list of strings
free(buffer); // Release input line's memory
return lines;
}
Note that the code uses plain char and not unsigned char. You face some issues if you use unsigned char because neither getline() nor strdup() expects to work with unsigned char. While you can cast your way around the issue, it is messy to do so.

copy data from a memory address to another memory address, 752 bytes at a time

i want to copy data from a memory address to another memory address, 752 bytes at a time . without the for loop i am able to copy 752 bytes just once. how do i do it again and again 480 times and i need to increment my destination address so that all the 752 bytes data gets stored one after another in destination memory block. how can i do that? this is the solution that i came up with but its not working please help. Thank you .
volatile unsigned char *DAQ_BUFF = (unsigned char *)0xC6010000;
extern unsigned char *DAQ_BUFF;
unsigned char *Dest = (unsigned char *)0xC6020000;
int lv;
for(lv=0;lv<480;lv++)
{
memcpy(Dest,DAQ_BUFF,752);
Dest=Dest+752;
}
Four things i noticed:
You are using memcpy 3 times
You dont increment DAQ_BUFF as Rowland said
You are using memcpy(&Dest,&DAQ_BUFF,300); instead of memcpy(Dest,DAQ_BUFF,300);
And Dest is not initialized
unsigned char *Dest = something;
int lv;
for(lv = 0; lv < 480; lv++){
memcpy(Dest, DAQ_BUFF, 752);
Dest += 752;
DAQ_BUFF += 752;
}
valter
I think that small change in your loop will satisfy the situation
Here is the modified loop
volatile unsigned char *DAQ_BUFF = (unsigned char *)0xC6010000;
extern unsigned char *DAQ_BUFF;
unsigned char *Dest;
int lv,rv;
for(lv=0;lv<480;lv++)
{
memcpy(&Dest,&DAQ_BUFF+752*lv,300);
memcpy(&Dest+300,&DAQ_BUFF+300+752*lv,300);
memcpy(&Dest+600,&DAQ_BUFF+600+752*lv,152);
Dest=Dest+752;
}
I think the following should work, see my comment on your question for an explanation. Can you explain to me why the memcpy only goes in steps of 300 bytes?
volatile unsigned char *DAQ_BUFF = (unsigned char *)0xC6010000;
extern unsigned char *DAQ_BUFF;
unsigned char *Dest = (unsigned char *)0xC6020000;
int lv;
for(lv=0;lv<480;lv++)
{
memcpy(Dest, DAQ_BUFF, 300);
memcpy(Dest+300, DAQ_BUFF+300, 300);
memcpy(Dest+600, DAQ_BUFF+600, 152);
Dest += 752;
}
Your code makes me assume that DAQ_BUFF is large enough to hold 752 bytes. The reason for me to assume this is because there is no signal/flag checking to see if the 'next 300' bytes of data is 'valid' in your DAQ_BUFF. If you do need to check this I would have expected something like this:
for(lv=0;lv<480;lv++)
{
while (DAQ_BUFF_DATA_IS_NOT_VALID); /* wait for DAQ data to be valid */
memcpy(Dest, DAQ_BUFF, 300);
/* if DAQ_BUFF can only hold 300 bytes then it must be read from the beginning again */
while (DAQ_BUFF_DATA_IS_NOT_VALID); /* wait for DAQ data to be valid */
memcpy(Dest+300, DAQ_BUFF, 300);
while (DAQ_BUFF_DATA_IS_NOT_VALID); /* wait for DAQ data to be valid */
memcpy(Dest+600, DAQ_BUFF, 152);
Dest += 752;
}
That seems more like a piece of code that has a DAQ_BUFFER_SIZE of 300.
If that is not the case and your DAQ_BUFFER_SIZE is large enough to commodate the 752 bytes I would expect the following:
for(lv=0;lv<480;lv++)
{
/* Do you first need to check if DAQ_BUFF-data is valid? */
memcpy(Dest, DAQ_BUFF, 752);
Dest += 752;
}
int a[5] = {1,2,3,4,5}
int *p = a;
for(i=0;i<5;i++)
{
printf("array value is %d pointer poiniting to %p ",*(p+i),p);
}
if you run this code everytime the value of p will be same
as u are incrementing the pointer only adding it. fix the incrementation either like
p = p+1;
p++;
In your case Dest and DAQ_BUFF.
Note: check if you have initialized the pointers correctly.(May be the code is missing )
or it will pointing to random memory

free() collecting garbage value in c code and code doesn't work even when setting the pointer to NULL after freeing

When I try to call free() function to free the memory, it isn't working properly. Here is my code:
unsigned char *indata;
unsigned char *outdata;
int file_func(const char *filename) {
//some other variables
for(i=0;i < no_of_files;i++) {
indata = malloc(sizeof(unsigned char));
outdata = malloc(sizeof(unsigned char));
//counts the number of characters from filename
numCharacters = readfile(filename, indata);
/* perform some operation on indata and get outdata(size is same as indata)*/
writefile(filename, outdata); //writes outdata to filename
free(indata);
free(outdata);
}
}
The above code does not work properly because free() is storing some random garbage value at indata & outdata(as they become dangling pointers). So I tried setting the pointers to null after freeing since I'm reusing the same pointers as:
free(indata);
indata = NULL;
free(outdata);
outdata = NULL;
Even then my code gets crashed as :
double free or corruption (out): 0x00000000025aa240 *
How can I overcome this problem or is there any other alternative to use dynamic sized pointers in a loop. Thank you.
You're only allocating 1 byte (sizeof(unsigned char)) for each of those variables. Either that's a mistake and you wanted to allocate sizeof(unsigned char) * some_number where some_number is dynamic, or you could just allocate on the stack:
unsigned char indata, outdata; // then use &indata and &outdata where you need a pointer
or
unsigned char indata[some_number];
unsigned char outdata[some_number];
or you can malloc once before the loop and free once after it.
The double free problem looks like one of the functions you're calling in the loop is calling free. Look carefully at readfile and writefile.

Find the size of a string pointed by a pointer

#include <stdio.h>
int main ()
{
char *ptr = "stackoverflow"
}
Is there any way to find the length of stackoverflow pointed by ptr, as sizeof ptr always gives 4
Use strlen to find the length of (number of characters in) a string
const char *ptr = "stackoverflow";
size_t length = strlen(ptr);
Another minor point, note that ptr is a string literal (a pointer to const memory which cannot be modified). Its better practice to declare it as const to show this.
sizeof() returns the size required by the type. Since the type you pass to sizeof in this case is a pointer, it will return size of the pointer.
If you need the size of the data pointed by a pointer you will have to remember it by storing it explicitly.
sizeof() works at compile time. so, sizeof(ptr) will return 4 or 8 bytes typically. Instead use strlen.
The strlen() function provided by string.h gives you how many "real characters" the string pointed by the argument contains. However, this length does not include the terminating null character '\0'; you have to consider it if you need the length to allocate memory.
That 4 bytes is the size of a pointer to char on your platform.
#include<stdio.h>
main()
{
int mystrlen(char *);
char str[100];
char *p;
p=str;
printf("Enter the string..?\n");
scanf("%s",p);
int x=mystrlen(p);
printf("Length of string is=%d\n",x);
}
int mystrlen(char *p)
{
int c=0;
while(*p!='\0')
{
c++;
*p++;
}
return(c);
}
simple code to understand
You are looking for the strlen() function.
You can try using:
char *ptr = "stackoverflow"
size_t len = strlen(ptr);
if ptr length is an argument of a function it's reasonable to use pointers as a strings. we can get string length by following code:
char *ptr = "stackoverflow";
length=strlen((const char *)ptr);
And for more explanation, if string is an input string by user with variable length, we can use following code:
unsigned char *ptr;
ptr=(unsigned char *)calloc(50, sizeof(unsigned char));
scanf("%s",ptr );
length=strlen((const char *)ptr);
Purely using pointers you can use pointer arithmetic:
int strLen(char *s)
{
int *p = s;
while(*p !=’\0’)
{
p++; /* increase the address until the end */
}
Return p – s; /* Subtract the two addresses, end - start */
}
Even though this is a generic C question, it gets pretty high hits when looking this question up for C++. Not only was I in C/C++ territory, I also had to be mindful of Microsoft's Security Development Lifecycle (SDL) Banned Function Calls for a specific project which made strlen a no-go due to,
For critical applications, such as those accepting anonymous Internet connections, strlen must also be replaced...
Anyway, this answer is basically just a twist on the answers from the others but with approved Microsoft C++ alternative function calls and considerations for wide-character handling in respect to C99's updated limit of 65,535 bytes.
#include <iostream>
#include <Windows.h>
int wmain()
{
// 1 byte per char, 65535 byte limit per C99 updated standard
// https://stackoverflow.com/a/5351964/3543437
const size_t ASCII_ARRAY_SAFE_SIZE_LIMIT = 65535;
// Theoretical UTF-8 upper byte limit of 6; can typically use 16383 for 4 bytes per char instead:
// https://stijndewitt.com/2014/08/09/max-bytes-in-a-utf-8-char/
const size_t UNICODE_ARRAY_SAFE_SIZE_LIMIT = 10922;
char ascii_array[] = "ACSCII stuff like ABCD1234.";
wchar_t unicode_array[] = L"Unicode stuff like → ∞ ∑ Σὲ γνωρίζω τὴν ደሀ ᚦᚫᛏ.";
char * ascii_array_ptr = &ascii_array[0];
wchar_t * unicode_array_ptr = &unicode_array[0];
std::cout << "The string length of the char array is: " << strnlen_s(ascii_array_ptr, ASCII_ARRAY_SAFE_SIZE_LIMIT) << std::endl;
std::wcout << L"The string length of the wchar_t array is: " << wcsnlen_s(unicode_array_ptr, UNICODE_ARRAY_SAFE_SIZE_LIMIT) << std::endl;
return 0;
}
Output:
The string length of the char array is: 27
The string length of the wchar_t array is: 47
strlen() gives you the exact length of the string [excluding '\0']
sizeof() gives you the size of the data type used.
// stackoverflow = 13 Characters
const char* ptr = "stackoverflow";
strlen(ptr); // 13 bytes - exact size (NOT includes '\0')
sizeof(ptr); // 4 bytes - Size of integer pointer used by the platform
sizeof(*ptr); // 1 byte - Size of char data type
strlen("stackoverflow"); // 13 bytes - exact size
sizeof("stackoverflow"); // 14 bytes - includes '\0'
#include<stdio.h>
int main() {
char *pt = "String of pointer";
int i = 0;
while (*pt != '\0') {
i++;
pt++;
}
printf("Length of String : %d", i);
return 0;
}
We can also use strlen() function or sizeof() operator which is builtin in C.
We can also take help of pointer arithmetic as above example.

convert uint8_t array to char array in c

Initially I want to convert this uint8_t array to a char array in c. I have been a little stuck trying to resolve this problem. My first alternative solution is to copy another type value to the temporary one, copy the tmp value to a writable char, and then remove tmp value from memory. By the way this is used to accompany a blake hash function. Here is my code snippet:
char * bl(char *input)
{
uint8_t output[64];
char msg[]= "";
char *tmp;
int dInt;
memset(output,0,64);
tmp = (char*) malloc(64);
if (!tmp){
exit( 1);
}
dInt = strlen(input);
if (dInt > 0xffff){
exit( 1);
}
uint8_t data[dInt];
memset(data,0, dInt);
strlcpy(data,input,dInt);
uint64_t dLen =dInt;
blake512_hash(output, data,dLen);
int k;
for (k=0;k<64;k++){
tmp[k] = output[k]; //does this "copy" is buggy code?
}
memcpy(msg, tmp,64);
//so here I can to delete tmp value
// I dont want there were left unused value in memory
// delete tmp;
free(tmp);
return msg;
}
I think the code above is still not efficient, so what are your opinion, hints and the fixes?
Thank you very much before!
First of all, you should never return a pointer to a local variable since the variable will be destroyed by the time the function exits. You should probably want to pass the output array to bl function and use that to output the string.
For most cases(if uint8_t IS char, which is usually the case), memcpy(msg, output, 64) should be sufficient. If you want to be strict about it(quite frankly blake512_hash shouldn't return uint8_t array in the first place if you are expecting char array as the output all the time), you could simply call msg[k] = (char)tmp[k] in your for loop and remove memcpy.
A bit much is wrong here.
dInt = strlen(input) + 1; // dInt is the size of the string including the terminating '\0'.
strlcpy indeed uses the size, not strlen.
msg = tmp; and not freeing tmp. As msg is const char* "" (in C++ terms).

Resources