这是我大学一位老师的作业。
我不明白为什么代码会泄漏内存;有人可以帮助我吗?
我使用了很多人工智能来帮助,但仍然没有任何线索。
(不是母语英语,抱歉)
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int *digitos;
int ndigitos;
char sinal;
} BigNumber;
BigNumber scanBigNumber()
{
BigNumber inp;
char *s = malloc(sizeof(char));
int l = 1;
char aux;
printf("Enter Number: ");
scanf("%c", &aux);
if (aux == '-')
{
inp.sinal = aux;
scanf("%c", &aux);
}
else
inp.sinal = '+';
while (aux != '\n')
{
l++;
s = realloc(s, l * sizeof(char));
s[l - 2] = aux;
scanf("%c", &aux);
}
inp.digitos = malloc((l - 1) * sizeof(int));
inp.ndigitos = l - 1;
for (int i = 0; i < inp.ndigitos; i++)
inp.digitos[i] = s[i] - 48;
free(s);
return inp;
}
void addZeros(BigNumber *inp, int size)
{
if (size <= inp->ndigitos)
{
return;
}
int *newDigitos = malloc(size * sizeof(int));
int diff = size - inp->ndigitos;
for (int i = 0; i < diff; i++)
{
newDigitos[i] = 0;
}
for (int i = 0; i < inp->ndigitos; i++)
{
newDigitos[i + diff] = inp->digitos[i];
}
free(inp->digitos);
inp->digitos = newDigitos;
inp->ndigitos = size;
}
int getGreaterArraySize(BigNumber *inp1, BigNumber *inp2)
{
if (inp1->ndigitos > inp2->ndigitos)
return inp1->ndigitos;
if (inp1->ndigitos < inp2->ndigitos)
return inp2->ndigitos;
else
return inp1->ndigitos;
}
void printArray(int *v, int n)
{
int isZero = 0, k = -1;
for (int i = 0; i < n; i++)
if (v[i] != 0)
{
isZero = 1;
k = i;
break;
}
if (k == -1)
{
printf("0");
return;
}
if (!isZero)
for (int i = 0; i < n; i++)
printf("%d", v[i]);
else
for (int i = k; i < n; i++)
printf("%d", v[i]);
}
void inverterArray(int *arr, int tamanho)
{
int inicio = 0;
int fim = tamanho - 1;
while (inicio < fim)
{
// Trocar os elementos no início e no final
int temp = arr[inicio];
arr[inicio] = arr[fim];
arr[fim] = temp;
// Avançar o ponteiro do início e retroceder o ponteiro do final
inicio++;
fim--;
}
}
// =================================================================
// OPERAÇÕES
// =================================================================
BigNumber soma(BigNumber *inp1, BigNumber *inp2)
{
int n2 = 0;
int n = getGreaterArraySize(inp1, inp2);
BigNumber temp;
temp.digitos = calloc(n, sizeof(int));
temp.ndigitos = n;
if (inp1->ndigitos > inp2->ndigitos)
addZeros(inp2, n);
if (inp1->ndigitos < inp2->ndigitos)
addZeros(inp1, n);
int carry = 0;
for (int i = n - 1; i >= 0; i--)
{
int sum = 0;
if (i < inp1->ndigitos)
sum += inp1->digitos[i];
if (i < inp2->ndigitos)
sum += inp2->digitos[i];
sum += carry;
temp.digitos[i] = sum % 10;
carry = sum / 10;
n2++;
}
if (carry > 0)
{
addZeros(&temp, n + 1);
temp.digitos[0] = carry;
}
return temp;
}
BigNumber subtract(BigNumber *inp1, BigNumber *inp2)
{
int n = getGreaterArraySize(inp1, inp2);
BigNumber temp;
temp.digitos = calloc(n, sizeof(int)); // Correct the size to 'n'
temp.ndigitos = n;
int borrow = 0;
if (inp1->ndigitos > inp2->ndigitos)
addZeros(inp2, n);
else if (inp1->ndigitos < inp2->ndigitos)
addZeros(inp1, n);
for (int i = n - 1; i >= 0; i--)
{
int dif = inp1->digitos[i] - inp2->digitos[i] - borrow;
if (dif < 0)
{
dif += 10; // Change to base decimal
borrow = 1;
}
else
borrow = 0;
temp.digitos[i] = dif;
}
// // Remove leading zeros
// int firstNonZero = 0;
// while (firstNonZero < n && temp.digitos[firstNonZero] == 0)
// {
// firstNonZero++;
// }
// // If all digits are zero, keep a single zero
// if (firstNonZero == n)
// {
// free(temp.digitos);
// temp.digitos = calloc(1, sizeof(int));
// temp.ndigitos = 1;
// }
// else
// {
// // Adjust the size and digits if there were leading zeros
// int newSize = n - firstNonZero;
// int *newDigits = malloc(newSize * sizeof(int));
// for (int i = firstNonZero; i < n; i++)
// {
// newDigits[i - firstNonZero] = temp.digitos[i];
// }
// free(temp.digitos);
// temp.digitos = newDigits;
// temp.ndigitos = newSize;
// }
return temp;
}
BigNumber multiply(BigNumber *num1, BigNumber *num2)
{
int i, j, carry;
BigNumber temp;
temp.digitos = calloc(num1->ndigitos + num2->ndigitos, sizeof(int));
temp.ndigitos = num1->ndigitos + num2->ndigitos;
for (i = 0; i < num1->ndigitos; i++)
{
carry = 0;
int digit1 = num1->digitos[num1->ndigitos - 1 - i];
for (j = 0; j < num2->ndigitos; j++)
{
int digit2 = num2->digitos[num2->ndigitos - 1 - j];
int sum = digit1 * digit2 + temp.digitos[i + j] + carry;
carry = sum / 10;
temp.digitos[i + j] = sum % 10;
}
if (carry > 0)
{
temp.digitos[i + num2->ndigitos] += carry;
}
}
inverterArray(temp.digitos, temp.ndigitos);
// int pos = num1->ndigitos + num2->ndigitos - 1;
// while (pos >= 0 && temp.digitos[pos] == 0)
// {
// pos--;
// }
// // Print the result
// printf("\n\n\n\n\nResult of multiplication: ");
// for (; pos >= 0; pos--)
// {
// printf("%d", temp.digitos[pos]);
// }
// printf("\n");
return temp;
}
// =================================================================
// =================================================================
// =================================================================
void limparBuffer()
{
int c;
while ((c = getchar()) != '\n')
;
}
int comparaModulo(BigNumber inp1, BigNumber inp2)
{
if (inp1.ndigitos > inp2.ndigitos)
return 1;
else if (inp1.ndigitos < inp2.ndigitos)
return 2;
else if (inp1.ndigitos == inp2.ndigitos)
for (int i = 0; i < inp1.ndigitos; i++)
{
if (inp1.digitos[i] > inp2.digitos[i])
return 1;
else if (inp1.digitos[i] < inp2.digitos[i])
return 2;
else if (inp1.digitos[i] == inp2.digitos[i])
continue;
}
return 1;
}
BigNumber operationHandler(BigNumber inp1, BigNumber inp2, char signal)
{
// =================================================================
// SOMA
// =================================================================
BigNumber inpRes;
int maiorNum = comparaModulo(inp1, inp2);
if (signal == '+')
{
// 8 + 4
if (inp1.sinal == '+' && inp2.sinal == '+')
{
inpRes = soma(&inp1, &inp2);
inpRes.sinal = '+';
}
else if (inp1.sinal == '+' && inp2.sinal == '-')
{
if (maiorNum == 1)
// 8+ (-4)
{
inpRes = subtract(&inp1, &inp2);
inpRes.sinal = '+';
}
else if (maiorNum == 2)
// 4+ (-8)
{
inpRes = subtract(&inp2, &inp1);
inpRes.sinal = '-';
}
}
else if (inp1.sinal == '-' && inp2.sinal == '+')
{
if (maiorNum == 1)
// - 8 + 4
{
inpRes = subtract(&inp1, &inp2);
inpRes.sinal = '-';
}
else if (maiorNum == 2)
// -4 + 8
{
inpRes = subtract(&inp2, &inp1);
inpRes.sinal = '+';
}
}
else if (inp1.sinal == '-' && inp2.sinal == '-')
{
//-8 + (-4)
inpRes = soma(&inp1, &inp2);
inpRes.sinal = '-';
}
}
// =================================================================
// SUBTRAÇÃO
// =================================================================
else if (signal == '-')
{
if (inp1.sinal == '+' && inp2.sinal == '+')
{
if (maiorNum == 1)
{
inpRes = subtract(&inp1, &inp2);
inpRes.sinal = '+';
}
else if (maiorNum == 2)
{
inpRes = subtract(&inp2, &inp1);
inpRes.sinal = '-';
}
}
else if (inp1.sinal == '+' && inp2.sinal == '-')
{
inpRes = soma(&inp1, &inp2);
inpRes.sinal = '+';
}
else if (inp1.sinal == '-' && inp2.sinal == '+')
{
inpRes = soma(&inp2, &inp1);
inpRes.sinal = '-';
}
else if (inp1.sinal == '-' && inp2.sinal == '-')
{
if (maiorNum == 1)
{
inpRes = subtract(&inp1, &inp2);
inpRes.sinal = '-';
}
else if (maiorNum == 2)
{
inpRes = subtract(&inp2, &inp1);
inpRes.sinal = '+';
}
}
}
// =================================================================
// MULTIPLICAÇÃO
// =================================================================
else if (signal == '*')
{
inpRes = multiply(&inp1, &inp2);
if ((inp1.sinal == '+' && inp2.sinal == '-') || (inp1.sinal == '-' && inp2.sinal == '+'))
inpRes.sinal = '-';
else
inpRes.sinal = '+';
}
return inpRes;
}
int main()
{
// =================================================================
// Teste de operações
// =================================================================
int n = 0, p = 0;
BigNumber *res = NULL; // Inicializa o ponteiro para evitar problemas com free() posterior
res = malloc(sizeof(BigNumber));
while (!p)
{
BigNumber inp1, inp2;
char sinal;
inp1 = scanBigNumber();
if (inp1.digitos[0] == 1 && inp1.sinal == '-' && inp1.ndigitos == 1)
{
free(inp1.digitos); // Libera memória antes de encerrar o loop
break;
}
inp2 = scanBigNumber();
scanf(" %c", &sinal); // Adiciona um espaço antes do %c para consumir espaços em branco
res = realloc(res, (n + 1) * sizeof(BigNumber));
res[n] = operationHandler(inp1, inp2, sinal);
free(inp1.digitos);
free(inp2.digitos);
// limparBuffer();
n++;
}
for (int i = 0; i < n; i++)
{
printf("\nCaso de teste %d\n", i + 1);
if (res[i].sinal == '-')
printf("-");
printArray(res[i].digitos, res[i].ndigitos);
printf("\n");
free(res[i].digitos); // Libera a memória para cada resultado
}
free(res); // Libera o array de resultados
return 0;
}
该程序是一个“计算器”(仅适用于
+
,-
和*
)并且正在泄漏内存,可能在“添加零”功能中(我不太明白Valgrind告诉我的内容) ).
我唯一能让 valgrind 抱怨的是无效的操作符。例如,输入
"1\n" "1\n" "x"
。该问题并未表明在这种情况下会发生什么。我建议修改 operationHandler()
接口以支持返回错误或根本不调用它:
if(strchr("+-*", sinal)) {
res = realloc(res, sizeof *res * (n + 1));
res[n] = operationHandler(inp1, inp2, sinal);
n++;
}
在循环第一次迭代之后的
main()
中,输入缓冲区将包含读取运算符的试验\n
,因此BigNumber inp1 = scanBigNumber()
将始终读取空字符串。您需要用 limparBuffer()
刷新它,但它也应该处理 EOF:
int limparBuffer() {
for(;;) {
int c = getchar();
if(c == EOF || c == '\n')
return c;
}
}
// ...
if(limparBuffer() == EOF) {
free(inp1.digitos);
free(inp2.digitos);
break;
}
soma()
、subtract()
和 multiply()
不设置 temp.sinal
。