The C language sample of SAMURAI ENGINEERING SCHOOL is too dangerous.

https://www.sejuku.net/blog/25002

I haven't written C language for about 10 years now, but it's crazy.

To be honest, I think there is a risk of damaging the brand.

I copied it from the article.

#include <stdio.h>
#include <stdlib.h>
 
//Structure declaration
typedef struct {
  int num;
  char *str;
} strct;
 
int main(void) {
  //Generate entity
  strct *entity;
 
  //Allocate dynamic memory. Cast the allocated memory to the strct type pointer.
  entity = (strct*)malloc(sizeof(strct));
 
  //Member initialization
  entity->num = 0;
  entity->str = (char*)malloc(sizeof(32));
 
  //Assign a string to memory
  sprintf(entity->str, "%s %s!", "Hello", "World");
  printf("%s\n", entity->str);
 
  //Free memory
  free(entity->str);
  free(entity);
 
  return 0;
}

The first thing to worry about is this comment


  //Generate entity
  strct *entity;

What did you mean by the substance? This is just a pointer ...

Personally, I like to initialize the variable at the same time as it is declared, so I would write it like this.

  strct *entity = (strct *)malloc(sizeof(strct));

This area is still good. Here's the startling code.

  entity->str = (char*)malloc(sizeof(32));

I don't think you understand what sizeof (32) returns. 32 is an int type. This is the same as sizeof (int), and it depends on the processing system, but I think that 4 is returned for most patterns. In other words, I only have 4 bytes of memory, is that okay? (I'm not okay)

If you want to secure memory for 32 characters,

  entity->str = (char *)malloc(sizeof(char) * 32);

I think I should write. Also, since memory allocation may fail, it is better to check the return value for NULL. No, you should.

    //Assign a string to memory
    sprintf(entity->str, "%s %s!", "Hello", "World");

I'm scared, and honestly, I don't think I'll write this kind of code in production, but there is a risk of buffer overflow. In fact, early code has a buffer overflow.

So much for this code, the next code.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
//Structure declaration
typedef struct {
  int num;
  char *str;
} strct;
 
int main(void) {
  //Generate entity
  strct *entity;
 
  //Allocate dynamic memory. Cast the allocated memory to the strct type pointer.
  entity = (strct*)malloc(sizeof(strct));
 
  //Member initialization
  entity->num = 0;
  entity->str = (char*)malloc(sizeof(32));
 
  //Assign a string to memory
  sprintf(entity->str, "%s %s!", "Hello", "World");
  printf("%s\n", entity->str);
 
  char arr_str[] = "Hello USA!";
 
  //Memory size change
  entity->str = (char*)malloc(sizeof(arr_str));
  if(entity->str == NULL) {
    printf("memory error");
    return -1;
  }
 
  //Arr from the beginning of the address_Rewrite with NULL for the number of bytes of str
  memset(entity->str, '\0', sizeof(arr_str));
 
  printf("%s\n", entity->str);
 
  //Free memory
  free(entity->str);
  free(entity);
 
  printf("processing completion\n");
 
  return 0;
}

Since I pointed out sizeof (32) earlier, I will omit it.

  //Memory size change
  entity->str = (char*)malloc(sizeof(arr_str));

Hey, what about the original memory of ʻentity-> str`? It's the birth of a great memory leak.

Next!


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
//Structure declaration
typedef struct {
  int num;
  char *str;
} strct;
 
int main(void) {
  //Generate entity
  strct *entity;
 
  //Allocate dynamic memory. Cast the allocated memory to the strct type pointer.
  entity = (strct*)malloc(sizeof(strct));
 
  //Member initialization
  entity->num = 0;
  entity->str = (char*)malloc(sizeof(32));
 
  //Assign a string to memory
  sprintf(entity->str, "%s %s!", "Hello", "World");
  printf("%s\n", entity->str);
 
  //A copy of the entity of the structure
  strct *copy_entity;
  copy_entity = (strct*)malloc(sizeof(strct));
  memcpy(copy_entity, entity, sizeof(strct)); //Member pointers are shallow copies
 
  //Since it is a shallow copy, the value of the copy destination changes when the value of the copy source changes.
  strcpy(entity->str, "Hello Japan!");
  printf("%s, %s\n", entity->str, copy_entity->str);
 
  //Individual members need to be copied to make a deep copy
  copy_entity->str = (char*)malloc(sizeof(32));
  strcpy(copy_entity->str, entity->str);
 
  //Because of the deep copy, the copy destination value does not change even if the copy source value changes.
  strcpy(entity->str, "Hello USA!");
  printf("%s, %s\n", entity->str, copy_entity->str);
 
  //Free memory
  free(copy_entity->str);
  free(copy_entity);
  free(entity->str);
  free(entity);
 
  return 0;
}

sizeof (32) is ... (omitted)


  memcpy(copy_entity, entity, sizeof(strct)); //Member pointers are shallow copies

I'm not saying it's bad, but for this pattern, I would write * copy_entity = * entity. If you want to make a sample of memcpy, you may prepare an array of structures.

last!


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
//Structure declaration
typedef struct {
  int num;
  char *str;
} strct;
 
int main(void) {
  //Generate entity
  strct *entity;
 
  //Allocate dynamic memory. Cast the allocated memory to the strct type pointer.
  entity = (strct*)malloc(sizeof(strct));
 
  //Member initialization
  entity->num = 0;
  entity->str = (char*)malloc(sizeof(32));
 
  //Assign a string to memory
  sprintf(entity->str, "%s %s!", "Hello", "World");
  printf("%s\n", entity->str);
 
  //A copy of the entity of the structure
  strct *copy_entity;
  copy_entity = (strct*)malloc(sizeof(strct));
  memcpy(copy_entity, entity, sizeof(strct)); //Member pointers are shallow copies
 
  //Comparison operation between copy source and copy destination
  if( memcmp(entity, copy_entity, sizeof(&copy_entity)) == 0) {
    printf("Structure entity%s and%s is the same\n", "entity", "copy_entity");
  } else {
    printf("Structure entity%s and%s is different\n", "entity", "copy_entity");
  }
 
  //To make a deep copy, you need to copy the member alone
  copy_entity->str = (char*)malloc(sizeof(32));
  strcpy(copy_entity->str, entity->str);
 
  //Comparison operation between copy source and copy destination
  if(memcmp(entity, copy_entity, sizeof(&copy_entity)) == 0) {
    printf("Structure entity%s and%s is the same\n", "entity", "copy_entity");
  } else {
    printf("Structure entity%s and%s is different\n", "entity", "copy_entity");
  }
 
  //Free memory
  free(copy_entity->str);
  free(copy_entity);
  free(entity->str);
  free(entity);
 
  return 0;
}

Is this code okay? (So it's not okay)


    //Comparison operation between copy source and copy destination
    if( memcmp(entity, copy_entity, sizeof(&copy_entity)) == 0) {
        printf("Structure entity%s and%s is the same\n", "entity", "copy_entity");
    } else {
        printf("Structure entity%s and%s is different\n", "entity", "copy_entity");
    }

In particular, sizeof (& copy_entity) Do you understand this meaning? The type of copy_entity is strct *, right? What happens if you add & to it?

Yes! Represents the strct ** type.

So what is that sizeof? ?? ??

・ ・ ・

It depends on the processing system, but in most cases, 4 or 8 will be returned. In other words, I think I'm comparing only the part of the structure that corresponds to ʻint num... If I had to rewrite it, it would besizeof (strct). Even if you make a mistake, it's not sizeof (copy_entity)`!

By the way, I'm talking about padding, so I think it's better to allocate memory for the structure and then initialize it using memset.

To be honest, I think it's better to create a comparison function and check the contents of the members instead of comparing with memcmp. In C ++, it's an overload of the = operator.

Finally··· Everyone makes mistakes. Hate the code, don't hate people. It's scary if you don't repeat the verification of technical articles.

Recommended Posts