Home > database >  Declaring char variable breaks program
Declaring char variable breaks program

Time:11-27

I am exploring .tga files.

I have fully working code that looks like this:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>

const int letterHeight = 34;
const int spacer = 5;

typedef struct{
    uint8_t idlength;
    uint8_t colourmaptype;
    uint8_t datatypecode;
    uint16_t colourmaporigin;
    uint16_t colourmaplength;
    uint8_t colourmapdepth;
    uint16_t x_origin;
    uint16_t y_origin;
    uint16_t width;
    uint16_t height;
    uint8_t bitsperpixel;
    uint8_t imagedescriptor;
} TGA_Header;

typedef struct
{
    uint8_t B;
    uint8_t G;
    uint8_t R;
} Pixel;

typedef struct{
    TGA_Header header;
    Pixel* pixels;
    int width;
    int height;
} Image;


void readHeader(TGA_Header* header, FILE* input_F){
    fread(&header->idlength, sizeof(header->idlength), 1, input_F);
    fread(&header->colourmaptype, sizeof(header->colourmaptype), 1, input_F);
    fread(&header->datatypecode, sizeof(header->datatypecode), 1, input_F);
    fread(&header->colourmaporigin, sizeof(header->colourmaporigin), 1, input_F);
    fread(&header->colourmaplength, sizeof(header->colourmaplength), 1, input_F);
    fread(&header->colourmapdepth, sizeof(header->colourmapdepth), 1, input_F);
    fread(&header->x_origin, sizeof(header->x_origin), 1, input_F);
    fread(&header->y_origin, sizeof(header->y_origin), 1, input_F);
    fread(&header->width, sizeof(header->width), 1, input_F);
    fread(&header->height, sizeof(header->height), 1, input_F);
    fread(&header->bitsperpixel, sizeof(header->bitsperpixel), 1, input_F);
    fread(&header->imagedescriptor, sizeof(header->imagedescriptor), 1, input_F);
}


void writeHeader(TGA_Header* header, FILE* output_F){
    fwrite(&header->idlength, sizeof(header->idlength), 1, output_F);
    fwrite(&header->colourmaptype, sizeof(header->colourmaptype), 1, output_F);
    fwrite(&header->datatypecode, sizeof(header->datatypecode), 1, output_F);
    fwrite(&header->colourmaporigin, sizeof(header->colourmaporigin), 1, output_F);
    fwrite(&header->colourmaplength, sizeof(header->colourmaplength), 1, output_F);
    fwrite(&header->colourmapdepth, sizeof(header->colourmapdepth), 1, output_F);
    fwrite(&header->x_origin, sizeof(header->x_origin), 1, output_F);
    fwrite(&header->y_origin, sizeof(header->y_origin), 1, output_F);
    fwrite(&header->width, sizeof(header->width), 1, output_F);
    fwrite(&header->height, sizeof(header->height), 1, output_F);
    fwrite(&header->bitsperpixel, sizeof(header->bitsperpixel), 1, output_F);
    fwrite(&header->imagedescriptor, sizeof(header->imagedescriptor), 1, output_F);
}


void image_load(Image* image, const char* path){
    FILE* input_F = fopen(path, "rb");
        
    readHeader(&image->header, input_F);

    image->width = image->header.width;
    image->height = image->header.height;

    image->pixels = (Pixel*) malloc(sizeof(Pixel) * image->header.width * image->header.height);
    fread(image->pixels, sizeof(Pixel), image->header.width * image->header.height, input_F);

    fclose(input_F);
}

void image_create(Image* image, const char* path){
    FILE* output_F = fopen(path, "wb");
        
    writeHeader(&image->header, output_F);
    fwrite(image->pixels, sizeof(Pixel), image->header.width * image->header.height, output_F);

    fclose(output_F);
}


void load_letters(Image (*letters)[26], const char* f){
    char path[101];

    for(int i=0; i<26; i  ){
        strcpy(path, f);
        strcat(path, "/");
        char c[2] = {(char)(65 i), '\0'};
        strcat(path, c);
        strcat(path, ".tga\0");

        image_load(&(*letters)[i], &path[0]);
    }
}


void drawLetter(Image* image, Image* letter, int X, int Y){
    Y  = letterHeight - letter->height;

    int letter_y = letter->height;
    int letter_x = letter->width;
    int image_x = image->width;

    for(int y=0; y<letter_y; y  ){
        for(int x=0; x<letter_x; x  ){
            if(letter->pixels[y*letter_x x].R != (uint8_t)0 || letter->pixels[y*letter_x x].G != (uint8_t)0 || letter->pixels[y*letter_x x].B != (uint8_t)0){
                image->pixels[(y Y)*image_x (x X)] = letter->pixels[y*letter_x x];
            }
        }
    }
}


void drawString(Image* image, Image (*letters)[26], char (*text)[101], int Y){
    int dejToSzajzym = 0;
    for(int i=0; i<strlen((*text)); i  ){
        dejToSzajzym  = (*letters)[(int)(*text)[i] - 65].width;
    }
    dejToSzajzym = dejToSzajzym/2;
    dejToSzajzym = image->width/2 - dejToSzajzym;

    for(int i=0; i<strlen(*text); i  ){
        if((*text)[i] != ' '){
            drawLetter(image, &(*letters)[(int)(*text)[i] - 65], dejToSzajzym, Y);
            dejToSzajzym  = (*letters)[(int)(*text)[i] - 65].width;
        }else{
            dejToSzajzym  = 10;
        }
    }
}
    
int main(int argc, char* argv[]){

    Image* image;
    Image letters[26];

    image_load(image, "img1.tga");
    load_letters(&letters, "font");

    /*
    char buffer[100];
    */

    drawString(image, &letters, "LOL", 5);
    image_create(image, "image.tga");

    free(image->pixels);
    image->pixels = NULL;
    for(int i=0; i<26; i  ){
        free(letters[i].pixels);
        letters[i].pixels = NULL;
    }
    
    return 0;
}

But when I write the declaration of buffer as shown (could be anywhere in main) the program immediately breaks. It doesn´t even need to do anything.

error:

Unable to open 'memmove-vec-unaligned-erms.S': Unable to read file '/build/glibc-YYA7BZ/glibc-
2.31/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S' 
(Error: Unable to resolve non-existing file '/build/glibc-YYA7BZ/glibc-2.31/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S').

BTW: Isn't there any easier way to copy the header data?

CodePudding user response:

BTW: Isn't there any easier way to copy the header data?

Yes, there is, and there are a couple of ways to do it. The fundamental observation is that you could write the header with fwrite(header, sizeof(*header), 1, fp), and read it with fread(header, sizeof(*header), 1, fp).

However, with the data structure as currently defined, there is some padding in the structure — one byte after datatypecode and another after colourmapdepth. If you moved colourmapdepth after datatypecode (or anywhere near the start of the structure before the first uint16_t member), you'd save two bytes in memory and have no padding bytes on disk. OTOH, there's not a lot of harm in the padding bytes being read/written. It isn't clear to me whether you're dealing with an externally imposed header structure or whether you're free to modify it.

The best way to avoid padding in a structure is to put the most stringently aligned types at the start of the structure (uint16_t is more stringently aligned than uint8_t) and less stringently aligned types at the end. That normally avoids holes in the structure. There can still be padding at the end of the structure even so.

CodePudding user response:

The compiler is attempting to call memmove and can't find it because you're running with no libraries.

Assuming you're doing what I think you're doing, the best way is to provide it. In another file, declare memmove like so.

void *memmove(void *sm, const void *tm, size_t n)
{
    char *s = (char *)sm;
    const char *t = (const char *)tm;
    if (s > t) {
        s  = n;
        t  = n;
        while (n--)
           *s-- = *t--;
    } else {
        while (n--)
           *s   = *t  ;
    }
    return sm;
}

You may have to fiddle with the declaration to get the compiler to accept it.

Note that this is not the best possible memmove, it's the simplest. If it's too slow, write or obtain a faster one.

  •  Tags:  
  • ctga
  • Related