The problem:
I need to malloc a struct to populate a char *[64] array. This array gets corrupted when I free the struct. Specifically the first index. How should I deal with this?
int main(void) {
char *names[64];
uint32_t aCount = 0;
uint32_t count = 0;
vkEnumerateInstanceExtensionProperties(NULL,&count, NULL);
VkExtensionProperties *extension_names = malloc(sizeof(VkExtensionProperties) * count);
vkEnumerateInstanceExtensionProperties(NULL,&count,extension_names);
for(uint32_t i = 0; i < count; i++) {
names[aCount++] = extension_names[i].extensionName;
}
printf("First extension available: %s\n",names[0]);
free(extension_names);
printf("First extension available: %s\n",names[0]);
return 0;}
Here is the result:
Before free()
First extension available: VK_KHR_device_group_creation
After free()
First extension available: ���yUU
You can use strdup to make copies of the strings and solve the "use after free" problem you are having:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define UNUSED(x) \
((void)(x))
#define VK_MAX_EXTENSION_NAME_SIZE 256
typedef struct VkExtensionProperties {
char extensionName[VK_MAX_EXTENSION_NAME_SIZE];
uint32_t specVersion;
} VkExtensionProperties;
void vkEnumerateInstanceExtensionProperties(void *unused,
uint32_t *count, VkExtensionProperties *result) {
UNUSED(unused);
*count = 64;
if (result) {
for (int index = 0; index < *count; index++) {
snprintf(result[index].extensionName,
sizeof(result->extensionName),
"extension%03d",
index);
}
}
}
int main()
{
char *names[64];
uint32_t aCount = 0;
uint32_t count = 0;
vkEnumerateInstanceExtensionProperties(NULL, &count, NULL);
VkExtensionProperties *extension_names = malloc(sizeof(VkExtensionProperties) * count);
vkEnumerateInstanceExtensionProperties(NULL, &count, extension_names);
for (uint32_t i = 0; i < count; i++) {
names[aCount++] = strdup(extension_names[i].extensionName);
}
printf("First extension available: %s\n", names[0]);
free(extension_names);
printf("First extension available: %s\n", names[0]);
return 0;
}
Output
First extension available: extension000
First extension available: extension000
I don't have Vulcan installed, so I simulated the behavior of the function you called.
Helpful GCC Flags
While I have your attention, don't forget to compile your code with -Wall -Werror to help you fix problems at compile time:
$ gcc -Wall -Werror -o program program.c
You are assigning names[aCount++] = extension_names[i].extensionName;
i.e. you are copying the extension_names in the array of pointers that is names.
You can only free extension_names after you are done with using names
You freed the strings, so not sure what you expected to happen. The second printf() will access freed memory. If you want to keep the strings around longer, you should copy the string data, not just the pointers to that data. Also, you need to write safer code to avoid buffer overflows (you're not checking if you're writing past the end of names, for example.)
for (uint32_t i = 0; i < count && aCount < 64; i++, aCount++) {
// +1 for the '\0' terminator
const size_t len = strlen(extension_names[i].extensionName) + 1;
names[aCount] = malloc(len);
memcpy(names[aCount], extension_names[i].extensionName, len);
}
Note that you now also have to free() each element in names when you no longer need it.
Related
This is a function to find union of strings.
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>
char* my_union(char* param_1, char* param_2)
{
char *res[strlen(param_1) + strlen(param_2)]; //allocate long enough string
//check if the letter is in result res string
for(int i = 0 ; i < strlen(param_1);i++){
if(strchr(*res,param_1[i]) == NULL){// this checks for duplicates
res[i] = param_1[i];
}
}
for(int i = 0 ; i < strlen(param_2);i++){
if (strchr(*res, param_2[i])== NULL){//this checks for duplicates too
*res[i] = param_2[i];
}
}
printf("%s\n", *res);
return *res;
}
int main(){
char *s1 = "zpadinton" ;
char *s2 = "paqefwtdjetyiytjneytjoeyjnejeyj";
my_union(s1,s2);// must return "zpadintoqefwjy"
//the union is zpadintoqefwjy
return 0;
}
Some fundamental bugs:
char *res[] is an array of pointers. You don't want that.
strlen(param_1) + strlen(param_2) is not long enough, you didn't allocate space for the null terminator.
return *res; returning a pointer to a local variable is always wrong, because that variable goes out of scope when the function returns.
You either need to let the called do the allocation and write to one of the passed parameters, or you need to allocate memory for the string dynamically.
Notably, since you incorrectly used an array of pointers, stuff like res[i] = param_1[i]; should not compile cleanly. You will get warnings "assignment from incompatible type"/"pointer from integer without a cast" or something like that.
Always read and correct warnings. For a beginner, a warning is pretty much 100% certain equal a bug. Crank up your warning level to the max and even better, block invalid code from compiling in the first place. For example gcc/clang/icc: -std=c11 -pedantic-errors -Wall -Wextra -Werror.
char *res[strlen(param_1) + strlen(param_2)]; //allocate long enough string
You cannot allocate dynamic length on stack. You need to allocate it on heap, like this:
char *res = malloc(strlen(param_1) + strlen(param_2)+1);
(Note: add an extra byte for the null terminator)
You need to set the buffer to zeros to be able to use strchr later:
memset(res, 0, strlen(param_1) + strlen(param_2)+1);
if(strchr(*res,param_1[i]) == NULL){// this checks for duplicates
res[i] = param_1[i];
}
strchr should take res, not *res.
Assignment to index i would not work, as you need to add the new character at the end of the result string.
int j=0;
for(int i = 0 ; i < strlen(param_1);i++){
if(strchr(res,param_1[i]) == NULL){// this checks for duplicates
res[j] = param_1[i];
j++;
}
}
for(i = 0 ; i < strlen(param_2);i++){
if (strchr(res, param_2[i])== NULL){//this checks for duplicates too
res[j] = param_2[i];
j++;
}
}
printf("%s\n", res);
return res;
I am wondering can pure C do following pseudo code?
for(int i = 0; i < N; i++)
func( Multi("str",i));
I know the feature char *tmp = "str1" "str1" and tried to combine that and macro. But, the only way I come up with is define several macro with different repeat times. My method is bad for concise, are there better method ?
edit:
expect Multi can return "str" * i times
e.g. char *tmp = Multi("str",3); // now tmp is "strstrstr"
Not if you expect to be able to use the run-time value of a variable to control the number of repetitions (unless the range of values of that variable is small and known at compile-time).
Macro expansion and literal string concatenation are done as phases during the compilation, before the executable has been produced. The program doesn't yet exist, and certainly cannot be run. The macro preprocessor only sees a variable as an identifier inside the text of the program.
If you will always use a literal integer, then it is possible to do the expansion with the macro preprocessor, although it does indeed require a lot of macros. There are some macro libraries which can help.
If you know the maximum number of repetitions (and have some runtime mechanism to verify that the limit is not exceeded), you could create a single string literal of the maximum size, perhaps using a macro library as mentioned above. You can then get a string literal containing fewer than this maximum by starting int the middle:
#define Multi(literal, rep) \
(&(REP(MAXREP, literal))[((sizeof literal)-1)*(MAXREP-rep)])
For that to work, MAXREP must be previously #defined as a (smallish) integer constant (not a constant expression).
Here's a complete example program, using BOOST_PP_REPEAT from the Boost preprocessor library to define REP:
#include <stdio.h>
#include <stdlib.h>
#include <boost/preprocessor/repeat.hpp>
#define MAXREP 80
#define REPEATER(z, n, literal) literal
#define REP(n, literal) BOOST_PP_REPEAT(n, REPEATER, literal)
#define Multi(literal, rep) \
(&(REP(MAXREP, literal))[((sizeof literal)-1)*(MAXREP-rep)])
int main(int argc, char** argv) {
int reps = 0;
if (argc > 1) reps = atoi(argv[1]);
if (reps <= 0) reps = MAXREP;
if (reps > MAXREP) {
fprintf(stderr, "Cannot do %d repetitions; maximum is %d\n", reps, MAXREP);
exit(1);
}
for (int i = 0; i < reps; ++i) printf("%s\n", Multi("foo", i));
return 0;
}
Sample run:
$ make rep
cc -O0 -Wall -ggdb -std=c11 -D_XOPEN_SOURCE=700 -mtune=native rep.c -o rep
$ ./rep 5
foo
foofoo
foofoofoo
foofoofoofoo
Perhaps something employing a compound literal (since C99) to form the space needed?
MULTI(some_string_literal, n) is valid until the end of the block. No need to free.
#include <string.h>
char *Multi(char *dest, const char *s, unsigned n) {
size_t len = strlen(s);
char *p = dest;
while (n-- > 0) {
memcpy(p, s, len);
p += len;
}
*p = 0;
return dest;
}
// compound literal v-------------------------------v
#define MULTI(s, n) Multi( (char [(sizeof(s) - 1)*n + 1]){0} , (s), (n))
#include <stdio.h>
int main() {
char *tmp = MULTI("str", 3);
printf("<%s>\n", tmp);
printf("<%s> <%s>\n", MULTI("str", 4), MULTI("str", 5));
printf("%p\n", MULTI("str", 6));
}
Sample output
<strstrstr>
<strstrstrstr> <strstrstrstrstr>
0xffffcb80
One way to implement this is to use strncpy and calloc to copy the original string several times into a new char array
char* repeat(char* orig, size_t times) {
if (times == 0) return calloc(1, sizeof(char)); // is the empty string
else {
size_t orig_length = strlen(orig);
size_t new_length = times * orig_length;
char* new_str = malloc((new_length + 1) * sizeof(char));
for (size_t i = 0; i < times; i++) {
strncpy(&new_str[orig_length * i], orig, orig_length);
}
new_str[new_length] = 0; // setting the null-byte
return new_str;
}
}
This function return always a new string, which needs to be freed with free before the last reference to it is lost or else you will have a memory leak.
This could also be done recursive, but this won't do much for this kind of function.
And this can most likly be optimized, feel free to suggest improvements.
Yes pure C can do a lot my friend, here I have written a function for you
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * strRepeat(char *str, int n) {
int len = strlen(str);
char *repeatedStr = (char *)malloc(len * n + 1);
if(repeatedStr == NULL) {
return NULL;
}
for(int i = 0;i < len * n; i++) {
repeatedStr[i] = str[i % len];
}
repeatedStr[len * n] = '\0';
return repeatedStr;
}
int main(void) {
char *s = strRepeat("str", 7);
printf("%s", s);
//output: strstrstrstrstrstrstr
free(s);
return 0;
}
I've been dealing with an annoying memory corruption error for a couple of hours. I've checked every related thread here, and I couldn't fix it.
First of all, I'm writing a simple Terminal in C. I'm parsing the commands between pipe (|) and redirection (>, <, etc.) symbols and place them in the queue. Nothing complicated!
Here's the data structure for the queue;
struct command_node {
int index;
char *next_symbol;
struct command_node *nextCommand;
int count;
char **args;
};
When I'm storing small strings in the **args pointer, everything works just fine. However, when one of the arguments is long, I get malloc(): memory corruption error. For example, the following 1st command works fine, the 2nd command causes the error
1st: ls -laF some_folder | wc -l
2nd: ls -laF /home/enesanbar/Application | wc -l
I run the debugger, it showed that the malloc() call for the new node in the queue causes the error.
newPtr = malloc( sizeof(CommandNode) );
I'm carefully allocating the array of strings and freeing after I'm done with them as follows:
char **temp = NULL;
temp = malloc(sizeof(char*) * number_of_args);
/* loop through the argument array */
for (i = 0; i < number_of_args; i++) {
/* ignore the remaining commands after ampersand */
if (strcmp(args[i], "&") == 0) return;
/* split commands by the redirection or pipe symbol */
if (!isSymbol(args[i])) {
temp[count] = malloc(sizeof(strlen(args[i])) + 1);
strcpy(temp[count], args[i]);
count++;
/* if it is the last argument, assign NULL to the symbol in the data structure */
if (i + 1 == number_of_args) {
insertIntoCommands(&headCommand, &tailCommand, temp, NULL, count);
for (j = 0; j < count; j++) free(temp[j]);
count = 0; // reset the counter
}
}
else {
insertIntoCommands(&headCommand, &tailCommand, temp, args[i], count);
for (j = 0; j < count; j++) free(temp[j]);
count = 0; // reset the counter
}
}
I must have missed something, or there's something I don't know about the **args fields and the allocation of the new node although it's nothing I haven't done before.
but how could wrapping a number around the sizeof cause an error in the allocation of a node? I'm just trying to understand out of curiosity.
Like I was saying in my comment, you try to get the size of the pointer inside the strlen function and not the lenght which is provided through the function.
Please take a look at the following:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main(void){
char *name = "Michi";
size_t length1, length2;
length1 = strlen(name);
length2 = sizeof strlen(name);
printf("Length1 = %zu\n",length1);
printf("Length2 = %zu\n",length2);
return 0;
}
Output:
Length1 = 5
Length2 = 8
One more thing, after you free(temp[j]) don't forget to free(temp) also.
Something like this:
#include <stdio.h>
#include <stdlib.h>
int main(void){
long unsigned int size = 2,i;
char **array;
array = malloc(sizeof(char*) * size * size);
if (array == NULL){
printf("Error, Fix it!\n");
exit(2);
}
for (i = 0; i < size; i++){
array[i] = malloc(sizeof(char*) * 100);
}
/* do code here */
for (i = 0; i < size; i++){
free(array[i]);
}
free(array);
return 0;
}
I have a piece of code that looks like this
#include <stdio.h>
int main()
{
int i;
int number_of_chunks = 12;
char *final_string = NULL;
for(i = 0; i < number_of_chunks; i++)
{
char *chunk = some_hash_table.pop(i);
asprintf(&final_string, "%s%s", (final_string==NULL?"":final_string), chunk);
}
free(final_string);
return 0;
}
Here I am concatinating string chunks dynamically, meaning I don't know the size of each chunk in advance. For this I am using asprintf. The code works fine, however rise some serious memory issue. My doubt is asprintf allocates memory in each iteration and the code loses pointer in each iteration. If there is any other way I can concate string inside loop please guide me
To put your question in the simplest possible way, what you are essentially trying to do with the above code is
1. Allocate memory to a pointer continuously(in your case 12 times in the for loop) and
2. free it at the end only once, which is causing memory leak.
Like in the below code
#include <stdio.h>
int main()
{
int i;
int number_of_chunks = 12;
char *final_string = NULL;
for(i = 0; i < number_of_chunks; i++)
{
/*For example: similar to what asprintf does, allocate memory to the pointer*/
final_string = malloc(1);
}
free(final_string);
return 0;
}
From the above example it is easily visible that you have allocated the memory 12 times but freed only once.
code snippet:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int i;
int number_of_chunks = 12;
char *final_string = NULL;
char *tmp = NULL;
for(i = 0; i < number_of_chunks; i++)
{
char *chunk = some_hash_table.pop(i);
asprintf(&final_string, "%s%s", (tmp==NULL?"":tmp), chunk);
if (tmp)
free(tmp);
tmp = final_string;
}
printf("%s\n", final_string);
free(final_string);
return 0;
}
Others have already pointed out that you lose the reference to all but the last allocation and that having the same string that is written to as printf argument is probably undefined behaviour, even more so as re-allocations might occur and invalidate the format argument.
You don't use asprintf's formatting capabilities, you use it only to concatenate strings, so you might want to take another approach. You could either collect the strings in an array, determine the needed length, allocate as appropriate and fill the allocated buffer with memcpy.
Or you could write a self-allocating string buffer similar to C++'s std::stringstream, for example:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
struct append_t {
char *str; /* string */
size_t len; /* length of string */
size_t size; /* allocated size */
};
void append(struct append_t *app, const char *str)
{
size_t len = strlen(str);
while (app->len + len + 1 >= app->size) {
app->size = app->size ? app->size * 2 : 0x100;
app->str = realloc(app->str, app->size);
/* error handling on NULL re-allocation */
}
strcpy(app->str + app->len, str);
app->len += len;
}
int main(int argc, char **argv)
{
struct append_t app = {NULL};
for (int i = 1; i < argc; i++) {
append(&app, argv[i]);
}
if (app.str) puts(app.str);
free(app.str);
return 0;
}
Hey guys this is my first post here and i was wondering if any of you can help me figure out how to sort array of pointers to structures. Here's my code and here's my assignment if anyone is interested http://i.imgur.com/yBKnZTx.png.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#define MAX 50
struct address
{
char name[50];
char street[50];
char citystate[50];
char zip[20];
};
int main()
{
struct address *ptr[50];
struct address tptr;
char buffer[80];
int count = 0;
for (int i = 0; i <MAX; i++)
{
ptr[i] = malloc(sizeof(struct address));
if (gets(buffer)== NULL)
{
break;
}
else
{
strcpy((*ptr[i]).name, buffer);
gets((*ptr[i]).street);
gets((*ptr[i]).citystate);
gets((*ptr[i]).zip);
free(ptr[i]);
count++;
}
}
for (int x = 0; x<count; x++)
{
for (int y = 0; y<count - 1; y++)
{
if ((*ptr[y]).zip>(*ptr[y + 1]).zip)
{
tptr = ptr[y + 1];
ptr[y + 1] = ptr[y];
ptr[y] = tptr;
}
}
}
for (int i = 0; i < count; i++)
{
puts((*ptr[i]).name);
puts((*ptr[i]).street);
puts((*ptr[i]).citystate);
puts((*ptr[i]).zip);
}
}
Problems I see in your code:
You are using gets. See another SO post that addresses the poblem of using gets. Use fgets instead.
if (fgets(buffer, sizeof(buffer), stdin)== NULL)
fgets((*ptr[i]).street, sizeof((*ptr[i]).street), stdin);
fgets((*ptr[i]).citystate, sizeof((*ptr[i]).citystate), stdin);
fgets((*ptr[i]).zip, sizeof((*ptr[i]).zip), stdin);
You are calling free on a pointer in the following line
free(ptr[i]);
and continue to use it later in the code. Remove that line. Add the code to free the allocated memory at the end of the function.
for (int i = 0; i < count; i++)
{
free(ptr[i]);
}
You are assigning a struct address* to a variable of type struct address in the following line:
tptr = ptr[y + 1];
and you are assigning a struct address to a variable of type struct address* in the following line:
ptr[y] = tptr;
both of them can be fixed by changing the type of tptr to struct address*.
struct address *tptr;
The following code is not appropriate for comparing two strings:
if ((*ptr[y]).zip>(*ptr[y + 1]).zip)
it only compares two pointer values. Use
if (strcmp((*ptr[y]).zip,(*ptr[y + 1]).zip) > 0)
Why do you want to free() the allocated memory once you fetch the data from the user?
You should free() the allocated memory at the end of the program, once after the printing is done.
struct address tptr; should be of type struct address *tptr; as you are assigning the value of the pointer.
Below are the changes:
1.
for (int i = 0; i <MAX; i++)
{
ptr[i] = malloc(sizeof(struct address));
if (gets(buffer)== NULL)
{
free(ptr[i]); /* free the memory if data not read */
break;
}
else
{
strcpy((*ptr[i]).name, buffer);
gets((*ptr[i]).street);
gets((*ptr[i]).citystate);
gets((*ptr[i]).zip);
/* Do not free the mem here as you are bound to lose the data */
count++;
}
}
2.
for (int i = 0; i < count; i++)
{
puts((*ptr[i]).name);
puts((*ptr[i]).street);
puts((*ptr[i]).citystate);
puts((*ptr[i]).zip);
free(ptr[i]); /* free the memory here */
}
PS : Using gets() is not a good idea. Check this Do not use gets for more info
First, when dealing with pointer to structs, proper member access is with the -> operator (e.g. ptr[i]->street). As others have pointed out, do NOT use gets. It is no longer part of the C library and was deprecated because it was insecure. Use fgets or getline instead.
Next, (and this is a matter of form) avoid hardcoded numbers in your code. Use #define to set your values. This allows easy adjustment in a single place if values change.
With that, you were not far off with your code. Making only those changes, deleting the unnecessary math.h and adding strcmp for your sort, you can sort your structures in ascending order by zip as follows:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 50
#define MAXL 80
#define MAXZ 20
struct address {
char name[MAX];
char street[MAX];
char citystate[MAX];
char zip[MAXZ];
};
int main ()
{
struct address *ptr[MAX];
struct address *tptr;
char buffer[MAXL];
int count = 0;
for (int i = 0; i < MAX; i++) {
ptr[i] = malloc (sizeof (struct address));
if (fgets (buffer, MAXL, stdin) == NULL) {
break;
} else {
strncpy (ptr[i]->name, buffer, MAXL);
ptr[i]->name[MAX - 1] = 0;
fgets (ptr[i]->street, MAX, stdin);
fgets (ptr[i]->citystate, MAX, stdin);
fgets (ptr[i]->zip, MAXZ, stdin);
count++;
}
}
for (int x = 0; x < count; x++) {
for (int y = 0; y < (count - 1); y++) {
if (strcmp (ptr[y]->zip, ptr[y + 1]->zip) > 0) {
tptr = ptr[y + 1];
ptr[y + 1] = ptr[y];
ptr[y] = tptr;
}
}
}
for (int i = 0; i < count; i++) {
printf ("\n%s", ptr[i]->name);
printf ("%s", ptr[i]->street);
printf ("%s", ptr[i]->citystate);
printf ("%s", ptr[i]->zip);
}
}
Input
$ cat dat/sortaddress.txt
some name
my street
my city, my state
55512
another name
another street
another city, another state
44412
Use/Output
$ ./bin/struct_address_sort <dat/sortaddress.txt
another name
another street
another city, another state
44412
some name
my street
my city, my state
55512
note: reading with fgets or getline will read the trailing newline and include that in the buffer. It is a good idea to strip the newline from your strings so you don't have miscellaneous newlines at the end of your data. There are many examples on StackOverflow.