0

I used GNU BC ( basic calculator ) for exponentiation 999,999 to 999,999 and it answered in 10 minutes but when I want to find 999,999 root of a big file ( 1.1 GB) it shows segfault after 5 hours and GDB core shows mpz_clear(y) is the problem and when I remove it , It takes 20 hours and nothing happens and loop doesn't finish ; Here's the code :

#include <gmp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void) {
    FILE *fr, *fw;
    char filename[200];
    int size = 0;
    unsigned long int rt = 2;
    unsigned char ch[1] = {112};

    printf("Enter filename :\n");
    scanf("%s", &filename);
    fr = fopen(filename, "rb+");

    if (fr == NULL) {
        fprintf(stderr, "Error during opening of file %s\n", filename);
        perror("");
        return 1;
    }

    fseek(fr, 0L, SEEK_END);
    size = ftell(fr);
    fseek(fr, 0L, SEEK_SET);

    unsigned char* buf = NULL;
    buf = malloc((size_t)size);

    fread(buf, size, 1, fr);
    if (ferror(fr)) {
        fprintf(stderr, "Error during reading from file %s\n", filename);
        perror("");
        fclose(fr);
        return 1;
    }
    fclose(fr);
    fr = NULL;

    mpz_t x;
    mpz_init(x);
    mpz_t y;
    mpz_init(y);

    mpz_import(x, size, 1, (size_t)1u, 0, 0, buf);

    do {
        mpz_root(y, x, rt);
        if ((mpz_cmp_ui(y, 999999)) < 0)
            break;
        else
            mpz_clear(y);
        rt++;
    } while (rt <= 99999);

    int rootnum = 0;

    while (rt != 0) {
        int num;
        num = rt / 10;
        ++rootnum;
    }

    memset(buf, 0u, size);

    mpz_export(buf, NULL, 1, (size_t)1u, 0, 0, y);

    printf("Enter copied filename :\n");
    scanf("%s", &filename);

    fw = fopen(filename, "wb");
    if (fw == NULL) {
        fprintf(stderr, "Error during opening of file %s\n", filename);
        perror("");
        return 1;
    }

    fwrite(buf, mpz_sizeinbase(y, 10), 1, fw);
    if (ferror(fw)) {
        fprintf(stderr, "Error during writing to file %s\n", filename);
        perror("");
        fclose(fw);
        return 1;
    }

    fclose(fw);

    fw = fopen(filename, "ab+");
    fwrite(ch, 1, 1, fw);

    fclose(fw);

    fw = fopen(filename, "ab+");
    fwrite(&rt, rootnum, 1, fw);

    fclose(fw);

    free(buf);
    mpz_clear(x);
    mpz_clear(y);

    return 0;
}

Can any one tell me why the loop doesn't finish and how to fix it ?

Thanks I will be grateful

Edit : The code has been changed but segfault still exist and when I use GDB for debugging and open core file and enter the where command GDB shows mpz_clear(y) and if I remove it ( of course with else option ) the loop never ends ; The new code :

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <gmp.h>

int main(void)
{

FILE * fr, * fw;
char filename[201];
unsigned long long int size = 0;
unsigned long int rt = 2;
unsigned char ch[1] = {112};

printf("Enter filename : ");
fgets(filename, 200, stdin);
filename[strlen (filename) - 1] = '\0';
fr = fopen(filename, "rb+");

if (fr == NULL)
{
    fprintf(stderr, "Error during opening of file %s\n", filename);
    perror("");
    return 1;
}

fseek(fr, 0L, SEEK_END);
size = ftell(fr);
fseek(fr, 0L, SEEK_SET);

if (size == -1)
{

fprintf(stderr, "Size doesn't match\n'");
perror("");
return 1;

}

if ( size > SIZE_MAX)
{

fprintf(stderr, "The size of file is greater than acceptable\n");
perror("");
return 1;

}

unsigned char * buf = NULL;
buf = malloc((size_t)size);
if(buf == NULL)
{

    fprintf(stderr, "Buffer failure\n");
    perror("");
    return 1;

}

int r;
r = fread(buf, size, 1, fr);
printf("%d\n", r);
if (ferror(fr))
{
    fprintf(stderr, "Error during reading from file %s\n", filename);
    perror("");
    fclose(fr);
    return 1;
}
fclose(fr);
fr = NULL;

mpz_t x;
mpz_init(x);
mpz_t y;
mpz_init(y);

mpz_import(x, size, 1, (size_t)1u, 0, 0, buf);

do
{
    mpz_root (y, x, rt);
    if ((mpz_cmp_ui(y, 999999))<0)
    break;
    else
    {
    mpz_clear(y);
    mpz_init(y);
    rt++;
}while(rt<=99999);

int rootnum = 0;
unsigned long int num = rt;

do
{

    num = num/10;
    ++rootnum;

}while(num != 0);

memset (buf, 0u, size);

mpz_export(buf, NULL, 1, (size_t)1u, 0, 0, y);

printf("\nEnter copied filename : ");
fgets(filename, 200, stdin);
filename[strlen (filename) - 1] = '\0';

fw = fopen(filename, "wb");
if (fw == NULL) {
    fprintf(stderr, "Error during opening of file %s\n", filename);
    perror("");
    return 1;
}

fwrite(buf, mpz_sizeinbase(y, 10), 1, fw);
if (ferror(fw)) {
    fprintf(stderr, "Error during writing to file %s\n", filename);
    perror("");
    fclose(fw);
    return 1;
}

fclose(fw);

fw = fopen(filename, "ab+");
if(fw == NULL)
printf("File can't be written\n'");
if(ferror(fw))
{

    fprintf(stderr, "Error during writing to file %s\n", filename);
    perror("");
    fclose(fw);
    return 1;
    
}
fwrite(ch, 1, 1, fw);

fclose(fw);

fw = fopen(filename, "ab+");
if(fw == NULL)
printf("File can't be written\n'");
if(ferror(fw))
{

fprintf(stderr, "Error during writing to file %s\n", filename);
    perror("");
    fclose(fw);
    return 1;
    
}
int w;
w = fwrite(&rt, rootnum, 1, fw);
printf("%d\n", w);

fclose(fw);

free(buf);
mpz_clear(x);
mpz_clear(y);

return 0;

}
9
  • Please use {} even for single statement ifs, to make more obvious what you think your code is doing. Also, some indentation would help with that (though it does NOT actually influence behaviour, other than in e.g. Python). Probably becaue of your use of break it won't matter, even if you are wrong about how if works without {}, but it would make reading so much easier. Commented Sep 9, 2024 at 20:26
  • 1
    How is the compression tag relevant to this? Commented Sep 9, 2024 at 20:36
  • scanf("%s", &filename); should be scanf("%199s", filename);. %s expects a char* but you give it a char(*)[200]. Better use fgets Commented Sep 9, 2024 at 20:37
  • @Yunnosch For one statements there's no need of {} It's good but not necessary Commented Sep 9, 2024 at 21:38
  • 1
    @HadiLovelorn Re: "They edited my post" - I edited your code to make it readable. Commented Sep 10, 2024 at 4:40

1 Answer 1

3

Many holes.

Save time. Enable all compiler warnings

Endless loop

rt is never changed. num assigned a value that is never used.
Unclear what OP's goal is here.

unsigned long int rt = 2;
...
while (rt != 0) {
    int num;
    num = rt / 10; // conversion from 'long unsigned int' to 'int' may change value 
    ++rootnum;
}

Overflow

size = ftell(fr); may lose upper bits. Better as long size = ftell(fr); and check that size is not -1 nor more than SIZE_MAX.

Buffer overflow and loss of space characters

scanf("%s", &filename); does not read file names with spaces in the name - nor filenames 200 or longer. Use fgets() and lop off a potential '\n'.

Failure to check allocation success

buf = malloc((size_t)size); should be followed by a buf == NULL check.

Failure to check read

fread(buf, size, 1, fr); should check the return value. Same for fwrite(&rt, rootnum, 1, fw);

Failure to check for success

fw = fopen(filename, "ab+"); deserves a following test: fw == NULL?


Likely more issues.

Sign up to request clarification or add additional context in comments.

10 Comments

Thank You ; Great points ..... I fixed some of them , But since my computer is weak and here's middle night ; I will report result tomorrow
I changed the loop as : int rootnum = 0; unsigned long int rootnum2 = rt; unsigned long int num; do { num = rootnum2/10; ++rootnum; }while(num != 0); But still get segfault ; num gets the value of nth root value of file divided by 10
@HadiLovelorn "I changed the loop ... still get segfault" --> Let me know how things are after applying all the other fixes, especially Enable all compiler warnings. Consider posting a small sample data file so we can have a minimal reproducible example.
Should I edit my original post or open a new topic ?
@HadiLovelorn If your original key problem is solved, complete this post and then add a new question. Add links to/from that post to this question. If the questioned issue here is not solved, append new code and details.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.