Trying to use memcpy to continuously update an array, but failing - c

Just some premilinary info, the below code is part of a user space HID driver Im building, so Im going to try my best
to skip over the sections relating to device conectivity, etc...
I have two main arrays that I focus on which is the buf[] array and the buffer[] array.
The buffer[] array will be comprised of ranges of hex values that are taken from the buf[] array and appended on to it.
With the purpose of the buffer[] basically holding a large number of bytes that can then be consumed else where.
But I seem to be running into issues with buffer size growing past 1400, I also feel as though my logic as far as adding
to the buffer is flawed and not working as I think it is. Is there another way that I should be going about trying to acomplish this end goal?
If this code does not show enough PLEASE let me know and I will make the neccesary edits, Im desperate for the help
and still very new to C. Thank you!
full code found here if necessary http://pastebin.com/cyawpXCq
int int main(int argc, char const *argv[])
{
unsigned char buf[64];
unsigned char buffer[1400]; //1400 is the max size this should ever be
int i;
size_t buffer_length = 0;
for (i = 0; i < 24; i++)
{
// in this loop I add elements to the buf[]
// these elements are sent to the device
// which then returns the buf[] with new elements
// in it.
// I then want to push a range of these elements
// into the buffer which I am attempeting like so
// I skip the first 7 elements and take the
// next 16 elements which follow and append those to
// the buffer[].
memcpy(buffer + buffer_length, buf + 8, 16);
printf("\nStored Buffer - \n");
for (size_t i= 0; i < sizeof(buffer); i++) {
printf("%02X ", buffer[i]);
}
// add another 16 to the length
buffer_length += 16;
// loop breaks based on another condition
break;
}
// This condition comes next and does a similar
// thing as above
if(true)
{
// buf[] gets returned to
// me containing hex values from a device. I now
// want to append these values into the buffer[]
// and take the 30 elements which come after the
// first 7.
memcpy(buffer + buffer_length, buf + 8, 30);
printf("\nStored Buffer - \n");
for (size_t i= 0; i < sizeof(buffer); i++) {
printf("%02X ", buffer[i]);
}
// add another 30 to the length
buffer_length += 30;
}
// this loop can can return up to about 200 unique buf[] arrays
// and again is doing a similar thing where buf[] is filled with device
// data
for( int address = 0x0370; address < 0x0370 + 1400 + 1400; address += 28)
{
// I want to append 28 elements following the 7th element from buf[]
// to the end of the buffer[] on each iteration
memcpy(buffer + buffer_length, buf + 8, 28);
printf("\nStored Buffer - \n");
for (size_t i= 0; i < sizeof(buffer); i++) {
printf("%02X ", buffer[i]);
}
// add 28 to length each time.
buffer_length += 28;
printf("buffer_length = %zu", buffer_length);
}
return 0;
}

Related

HEAP CORRUPTION DETECTED: after normal block(#87)

I'm trying to do a program that get number of names from the user, then it get the names from the user and save them in array in strings. After it, it sort the names in the array by abc and then print the names ordered. The program work good, but the problem is when I try to free the dynamic memory I defined.
Here is the code:
#include <stdio.h>
#include <string.h>
#define STR_LEN 51
void myFgets(char str[], int n);
void sortString(char** arr, int numberOfStrings);
int main(void)
{
int i = 0, numberOfFriends = 0, sizeOfMemory = 0;
char name[STR_LEN] = { 0 };
char** arrOfNames = (char*)malloc(sizeof(int) * sizeOfMemory);
printf("Enter number of friends: ");
scanf("%d", &numberOfFriends);
getchar();
for (i = 0; i < numberOfFriends; i++) // In this loop we save the names into the array.
{
printf("Enter name of friend %d: ", i + 1);
myFgets(name, STR_LEN); // Get the name from the user.
sizeOfMemory += 1;
arrOfNames = (char*)realloc(arrOfNames, sizeof(int) * sizeOfMemory); // Change the size of the memory to more place to pointer from the last time.
arrOfNames[i] = (char*)malloc(sizeof(char) * strlen(name) + 1); // Set dynamic size to the name.
*(arrOfNames[i]) = '\0'; // We remove the string in the currnet name.
strncat(arrOfNames[i], name, strlen(name) + 1); // Then, we save the name of the user into the string.
}
sortString(arrOfNames, numberOfFriends); // We use this function to sort the array.
for (i = 0; i < numberOfFriends; i++)
{
printf("Friend %d: %s\n", i + 1, arrOfNames[i]);
}
for (i = 0; i < numberOfFriends; i++)
{
free(arrOfNames[i]);
}
free(arrOfNames);
getchar();
return 0;
}
/*
Function will perform the fgets command and also remove the newline
that might be at the end of the string - a known issue with fgets.
input: the buffer to read into, the number of chars to read
*/
void myFgets(char str[], int n)
{
fgets(str, n, stdin);
str[strcspn(str, "\n")] = 0;
}
/*In this function we get array of strings and sort the array by abc.
Input: The array and the long.
Output: None*/
void sortString(char** arr, int numberOfStrings)
{
int i = 0, x = 0;
char tmp[STR_LEN] = { 0 };
for (i = 0; i < numberOfStrings; i++) // In this loop we run on all the indexes of the array. From the first string to the last.
{
for (x = i + 1; x < numberOfStrings; x++) // In this loop we run on the next indexes and check if is there smaller string than the currnet.
{
if (strcmp(arr[i], arr[x]) > 0) // If the original string is bigger than the currnet string.
{
strncat(tmp, arr[i], strlen(arr[i])); // Save the original string to temp string.
// Switch between the orginal to the smaller string.
arr[i][0] = '\0';
strncat(arr[i], arr[x], strlen(arr[x]));
arr[x][0] = '\0';
strncat(arr[x], tmp, strlen(tmp));
tmp[0] = '\0';
}
}
}
}
After the print of the names, when I want to free the names and the array, in the first try to free, I get an error of: "HEAP CORRUPTION DETECTED: after normal block(#87)". By the way, I get this error only when I enter 4 or more players. If I enter 3 or less players, the program work properly.
Why does that happen and what I should do to fix it?
First of all remove the unnecessary (and partly wrong) casts of the return value of malloc and realloc. In other words: replace (char*)malloc(... with malloc(..., and the same for realloc.
Then there is a big problem here: realloc(arrOfNames, sizeof(int) * sizeOfMemory) : you want to allocate an array of pointers not an array of int and the size of a pointer may or may not be the same as the size of an int. You need sizeof(char**) or rather the less error prone sizeof(*arrOfNames) here.
Furthermore this in too convoluted (but not actually wrong):
*(arrOfNames[i]) = '\0';
strncat(arrOfNames[i], name, strlen(name) + 1);
instead you can simply use this:
strcpy(arrOfNames[i], name);
Same thing in the sort function.
Keep your code simple.
But actually there are more problems in your sort function. You naively swap the contents of the strings (which by the way is inefficient), but the real problem is that if you copy a longer string, say "Walter" into a shorter one, say "Joe", you'll write beyond the end of the allocated memory for "Joe".
Instead of swapping the content of the strings just swap the pointers.
I suggest you take a pencil and a piece of paper and draw the pointers and the memory they point to.

Remove some elements from array and re-size array in C

Regards
I want to remove some elements from my array and re-size it.
for example my array is:
char get_res[6] = {0x32,0x32,0x34,0x16,0x00,0x00};
Now I want to remove elements after 0x16, so my desire array is:
get_res[] = {0x32,0x32,0x34,0x16};
what is solution?
You cannot resize arrays in C (unlike Python, for example). For real resizing, at least from an API user's point of view, use malloc, calloc, realloc, and free (realloc specifically).
Anyway, "resizing" an array can be imitated using
a delimiter; for example, a delimiter like 0xff could mark the end of the valid data in the array
Example:
#define DELIMITER 0xff
print_data(char* data) {
for (size_t i = 0; data[i] != DELIMITER; ++i)
printf("%x", data[i]);
}
a member counter; count the number of valid data from the beginning of the array onward
Example:
size_t counter = 5;
print_data(char* data) {
for (size_t i = 0; i < counter; ++i)
printf("%x", data[i]);
}
Notes:
Use unsigned char for binary data. char may be aliasing signed char, which you might run into problems with because signed char contains a sign bit.
There is no need to "remove" them. Just don't access them. Pretend like they don't exist. Same like in stacks, when you "pop" a value from the top of the stack, you just decrement the stack pointer.
Manipulating arrays in C isn't easy as it is for vector in C++ or List in Java. There is no "remove element" in C. I mean that you have to do the job yourself, that is, create another array, copy only the elements you want to this new array, and free the memory occupied by the previous one.
Can you do that? Do you want the code?
EDIT:
Try that. It's just a simple program that simulates the situation. Now, you have to see the example and adapt it to your code.
#include <stdio.h>
#include <stdlib.h>
int main() {
char get_res[6] = {0x32,0x32,0x34,0x16,0x00,0x00};
char target = 0x16;
int pos, i, length = 6; // or specify some way to get this number
for(i = 0; i < length; i++)
if(get_res[i] == target) {
pos = i;
break;
}
pos = pos + 1; // as you have to ignore the target itself
char *new_arr = malloc(pos);
for(i = 0; i < length; i++) {
new_arr[i] = get_res[i];
i++;
}
for(i = 0; i < pos; i++)
printf("%c ", new_arr[i]);
return 0;
}

Multiple string manipulation not working

I am trying to define multiple strings in a double array such that
values[0][]="something", values[1][]="something else...
I then want to pad the length of each string so that they are 128 characters.
Finally, I want to split the 128 string into 4-char strings and write them 4 by 4 (so 32 writes). I know I have several problems but can anyone assist?
I found the problem. Here is my code and it does what I want. Thanks to all the suggestions.
for(k=0;k<inputs;k++){//do for all inputs
flag = 0;
int len = strlen(values[k]);
int padded_len = 127;
int i;
//pad inputs
for(i = 0; i < padded_len-len; i++){
strcat(values[k], "0");
}
for (off = 0; off < 128; off += 4){
strncpy(temp[k], values[k]+off, 4);
temp[k] = '\0';
temp_int = *((uint32 *) &values[k][off]);
if(flag==0){
//write to HW regy
flag=1;
}
else{
//write to HW regx
flag=0;
}
}
Right off the bat, looks like you have an error with the padding section when referencing our values[] array, so it should be:
//pad inputs
for(i = 0; i < padded_len-len; i++){
strcat(values[k], "0");
}
EDIT:
Also, you need to increase the size of your string array to include room for the null terminator:
... char values[3][129]...

How to use strncpy with a for-loop in C?

I am writing a program which will take every 3 numbers in a file and convert them to their ASCII symbol. So I thought I could read the numbers into a character array, and then make every 3 elements 1 element in a second array, convert them to int and then print these as char.
I am stuck on taking every 3 elements, however. This is my code snippet for this part:
char arry[] = "073102109109112"; <--example string read from a file
char arryNew[16] = {0};
for(int i = 0; i <= sizeof(arryNew); i++){
strncpy(arryNew, arry, 3);
arryNew[i+3]='\0';
puts(arryNew);
}
What this code gives me is the first 3 numbers, fifteen times. I've tried incrementing i by 3, which gives me the first 3 numbers 5 times. How do I write a for-loop with strncpy so that after copying n chars, it moves to the next n chars?
You pass always the pointer to the beginning of the array, so you will always have the same result of course. You must include the loop counter to get at the next block:
strncpy(arryNew, &arry[i*3], 3);
Here you have a problem:
arryNew[i+3]='\0';
First of all, you don't need to set the null byte every time, because this will not change anyway. Additionally you will corrupt memory, because you use i+3 as the index so when you reach 14 and 15, it will write beyond the arrayboundary.
Your arrayNew must be longer, because your original array is 16 characters, and your target array is also. If you intend to have several 3char strings in there, then you must have 5*4 characters for your target, because each string also has the 0-byte.
And of course, you must also use the index here as well. The way it is written now, it will write beyond the array boundary, when i reaches 14 and 15.
So what you seem to want to do (not sure from your description) is:
char arry[] = "073102109109112"; <--example string read from a file
char arryNew[20] = {0};
for(int i = 0; i <= sizeof(arry); i++)
{
strncpy(&arryNew[i*4], &arry[i*3], 3);
puts(&arryNew[i*4]);
}
Or if you just want to have the individual strings printed then you can just do:
char arry[] = "073102109109112"; <--example string read from a file
char arryNew[4] = {0};
for(int i = 0; i <= sizeof(arry); i++)
{
strncpy(arryNew, &arry[i*3], 3);
puts(arryNew);
}
Making things a bit simpler: your target string doesn't change.
char arry[] = "073102109109112"; <--example string read from a file
char target[4] = {0};
for(int i = 0; i < strlen(arry) - 3; i+=3)
{
strncpy(target, arry + i, 3);
puts(target);
}
Decoding:
start at the beginning of arry
copy 3 characters to target
(note the fourth element of target is \0)
print out the contents of target
increment i by 3
repeat until you fall off the end of the string.
Some problems.
// Need to change a 3 chars, as text, into an integer.
arryNew[i] = (char) strtol(buf, &endptr, 10);
// char arryNew[16] = {0};
// Overly large.
arryNew[6]
// for(int i = 0; i <= sizeof(arryNew); i++){
// Indexing too far. Should be `i <= (sizeof(arryNew) - 2)` or ...
for (i=0; i<arryNewLen; i++) {
// strncpy(arryNew, arry, 3);
// strncpy() can be used, but we know the length of source and destination,
// simpler to use memcpy()
// strncpy(buf, a, sizeof buf - 1);
memcpy(buf, arry, N);
// arryNew[i+3]='\0';
// Toward the loop's end, code is writing outside arryNew.
// Lets append the `\0` after the for() loop.
// int i
size_t i; // Better to use size_t (or ssize_t) for array index.
Suggestion:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char Source[] = "073102109109112"; // example string read from a file
const int TIW = 3; // textual integer width
// Avoid sprinkling bare constants about code. Define in 1 place instead.
const char *arry = Source;
size_t arryLen = strlen(arry);
if (arryLen%TIW != 0) return -1; // is it a strange sized arry?
size_t arryNewLen = arryLen/TIW;
char arryNew[arryNewLen + 1];
size_t i;
for (i=0; i<arryNewLen; i++) {
char buf[TIW + 1];
// strncpy(buf, a, sizeof buf - 1);
memcpy(buf, arry, TIW);
buf[TIW] = '\0';
char *endptr; // Useful should OP want to do error checking
// TBD: test if result is 0 to 255
arryNew[i] = (char) strtol(buf, &endptr, 10);
arry += TIW;
}
arryNew[i] = '\0';
puts(arryNew); // prints Ifmmp
return 0;
}
You could use this code to complete your task i.e. to convert the given char array in form of ascii value.
char arry[] = "073102109109112";
char arryNew[16] = {0};
int i,j=0;
for(i = 0; i <= sizeof(arryNew)-2; i+=3)
{
arryNew[j]=arry[i]*100+arry[i+1]*10+arry[i+2]*1;
j++;
arryNew[j+1]='\0';
puts(arryNew);
}

C memcpy Not Behaving as Expected

This question is tied to Making an Array to Hold Arrays of Character Arrays in C
Borrowing code from there, I have something that looks like this (credit to luser droog for the nice example code):
enum { BUFSZ = 50 };
enum { STRVSZ = 40 };
enum { STRVVSZ = 20 };
char buf[BUFSZ + 1];
char *strv[STRVSZ + 1];
char **strvv[STRVVSZ + 1];
int j;
int i;
while(1){
fgets(buf, BUFSZ, infile);
i = 0;
strv[i] = strdup(buf);
strv[i+1] = NULL;
j = 0;
strvv[j] = calloc(i+1, sizeof *strvv[j]); // assuming i is the count of elements
memcpy(strvv[j], strv, i * sizeof *strvv[j]);
j++;
}
This might not run right out the door, but it illustrates something similar to what I'm running. Basically, the contents of strv needs to be stored in strvv after every iteration of the loop, and strv changes over time based on user input.
Using calloc and memcpy should have caused strvv to maintain copies of strv at each iteration of the loop independent of the values in strv. However, when I print out the contents of strvv, it prints out the same string for every entry, implying that the current approach is still moving pointers around and not making copies of strv in each strvv entry.
I'm not at all sure why this happens or how to fix it. memcpy should be making a byte level copy of what the pointers in strv point to =/.
This is closer to what I was trying to suggest earlier.
enum { BUFSZ = 50 };
enum { STRVSZ = 40 };
enum { STRVVSZ = 20 };
char buf[BUFSZ + 1];
char *strv[STRVSZ + 1];
char **strvv[STRVVSZ + 1];
int j; // indexes strv slices in strvv
int i; // indexes strings (char *s) in strv
j = 0; // j is index into strvv
while(!feof(infile)) {
i = 0; // i is index into strv
while(i < STRVSZ){
fgets(buf, BUFSZ, infile);
if (strcmp(buf,"END")==0) break; // end of a set
strv[i] = strdup(buf);
strv[i+1] = NULL;
i++;
} // i is count of strv
// copy strv into strvv
strvv[j] = calloc(i+1, sizeof *strvv[j]); // assuming i is the count of elements
memcpy(strvv[j], strv, (i+1) * sizeof *strvv[j]); // i+1 to copy the NULL pointer
j++; // index next element in strvv and a count of strvv
} // j is count of sets in strvv
It feels like a mess still.
Functions. It needs smaller, clearly defined functions. The variables here are all placeholders for something more meaningful.

Resources