[英]Assigning value to a pointer struct gives a segmentation fault
我創建了一個結構體和一個該類型的指針。 我使用 malloc 為它分配了內存,但是當我嘗試實際為其分配一些值(特別是從文件中讀取整數和浮點數)時,它給了我一個分段錯誤,說“在某個位置沒有可用於“ungetwc() 的源”。
以下是有關指針和結構的部分代碼:
typedef struct {
int *rain;
float *avgtemp;
float *avgwind;
} weather;
weather *year = (weather*) malloc(n*sizeof(weather));
if (year == NULL)
{
return 1;
}
for (i = 0; i!=12; i++)
{
fscanf(infile, "%i %f %f", (year+i)->rain, (year+i)->avgtemp, (year+i)->avgwind);
}
我想問題可能出在 fscanf 中缺少 & 但當我添加它時,我的 IDE 給了我一個警告,提示 int* 是預期的,但提供了 int**。
根據您的代碼,這是必需的:
typedef struct {
int *rain;
float *avgtemp;
float *avgwind;
} weather;
weather *years = malloc(n * sizeof(weather));
if (year == NULL) {
return 1;
}
weather *year = years;
for (i = 0; i < n; ++i, ++year) {
year->rain = malloc(sizeof(int));
year->avgtemp = malloc(sizeof(float));
year->avgwind = malloc(sizeof(float));
fscanf(infile, "%i %f %f",
year->rain, year->avgtemp, year->avgwind);
}
但是,我真正認為您想要的是不要在struct
使用指針:
typedef struct {
int rain;
float avgtemp;
float avgwind;
} weather;
weather *years = malloc(n * sizeof(weather));
if (year == NULL) {
return 1;
}
weather *year = years;
for (i = 0; i < n; ++i, ++year) {
fscanf(infile, "%i %f %f",
&year->rain, &year->avgtemp, &year->avgwind);
}
更新:
是的,我剛剛從結構中刪除了指針,它確實解決了我遇到的所有問題。 也許我誤解了我教授所說的。
也許。 第一種方法(即你的版本)的有效期為某些更復雜的用例。 例如,如果struct
有一個char *
用於字符串長度可以任意長的字符串。
第二個版本更慣用,更容易使用。
否則,在你的代碼中的其他地方,當訪問一個元素時,我們會做(例如) int rain = *year->rain;
而不是 [更簡單的] int rain = year->rain;
如果struct
成員之一需要是一組值(例如)結構用於年度報告,而我們需要(例如)每個月的月降雨量(與一年的累積降雨量相比),則可能沒問題rain
[再次] 是int *rain;
. 但是,鑒於這一點,由於一年中的月數是固定的,我們可以這樣做: int rain[12];
保持簡單。
在您的代碼中,您僅為一個結構分配了內存,但該結構的字段仍在“等待”地址分配。 指針只是內存中地址的別名,因此操作該地址更具人類可讀性。
有一些方法可以解決您的問題。 我創建了四個不同的函數,並使用了兩種不同類型的結構。
代碼:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int rain;
float avgtemp;
float avgwind;
} weather;
typedef struct {
int *rain;
float *avgtemp;
float *avgwind;
} weatherp;
/* Obtain amount of items in array (implemented in <sys/params.h> header). */
#define nitems(x) (sizeof((x)) / sizeof((x)[0]))
/* Ex. 1: Using array of defined size. */
void
first_option()
{
weather year[2];
int ii;
for (ii = 0; ii < nitems(year); ii++) {
fscanf(stdin, "%d %f %f", &year[ii].rain, &year[ii].avgtemp, &year[ii].avgwind);
}
for (ii = 0; ii < nitems(year); ii++) {
fprintf(stdout, "%d %f %f\n", year[ii].rain, year[ii].avgtemp, year[ii].avgwind);
}
}
/* Ex. 2: Using malloc(3). */
void
second_option()
{
const int n = 2;
weather *year = (weather *)malloc(n * sizeof(weather));
int ii;
for (ii = 0; ii < n; ii++) {
fscanf(stdin, "%d %f %f", &year[ii].rain, &year[ii].avgtemp, &year[ii].avgwind);
}
for (ii = 0; ii < n; ii++) {
fprintf(stdout, "%d %f %f\n", year[ii].rain, year[ii].avgtemp, year[ii].avgwind);
}
free(year);
}
/* Ex. 3: Values in struct are pointers. */
void
third_option()
{
const int n = 2;
weatherp *year = (weatherp *) malloc(n * sizeof(weatherp));
int ii;
for (ii = 0; ii < n; ii++) {
year[ii].rain = (int *)malloc(sizeof(int));
year[ii].avgtemp = (float *)malloc(sizeof(float));
year[ii].avgwind = (float *)malloc(sizeof(float));
fscanf(stdin, "%d %f %f", year[ii].rain, year[ii].avgtemp, year[ii].avgwind);
}
for (ii = 0; ii < n; ii++) {
fprintf(stdout, "%d %f %f\n", *year[ii].rain, *year[ii].avgtemp, *year[ii].avgwind);
}
for (ii = 0; ii < n; ii++) {
free(year[ii].rain);
free(year[ii].avgtemp);
free(year[ii].avgwind);
}
free(year);
}
/* Ex. 4: Using array of defined size but struct fields are pointers. */
void
fourth_option()
{
weatherp year[2];
int ii;
for (ii = 0; ii < nitems(year); ii++) {
year[ii].rain = (int *)malloc(sizeof(int));
year[ii].avgtemp = (float *)malloc(sizeof(float));
year[ii].avgwind = (float *)malloc(sizeof(float));
fscanf(stdin, "%d %f %f", year[ii].rain, year[ii].avgtemp, year[ii].avgwind);
}
for (ii = 0; ii < nitems(year); ii++) {
fprintf(stdout, "%d %f %f\n", *year[ii].rain, *year[ii].avgtemp, *year[ii].avgwind);
}
for (ii = 0; ii < nitems(year); ii++) {
free(year[ii].rain);
free(year[ii].avgtemp);
free(year[ii].avgwind);
}
}
int
main()
{
first_option();
second_option();
third_option();
fourth_option();
return (0);
}
在 functon first_option() 中,我定義了結構的二元素數組(定義為weather
類型)。 array 和 struct 字段都已經分配了內存,因為我沒有使用作為指針的字段,而是使用int
/ float
類型的實例。
在 functon second_option() 中,我定義了包含天氣結構實例的指針。 結構字段已經分配了內存,因為在結構內部我沒有使用作為指針的字段。 有int
/ float
類型的實例。 但我必須為指針分配內存。 與前面的示例相比,我沒有結構數組,因此我必須創建它。 因此,我為n
個weather
結構實例分配內存。 這就像為多個數據框(包含一些重要信息的容器/結構)創建多個 (n) 架子。 畢竟,malloc 分配的內存應該由free(3)
函數釋放。
在 functonthird_option () 中,我沒有為數組和結構字段定義內存。 如您所見,現在我使用了新創建的weatherp
類型。 在這種情況下,我必須為結構字段和數據框(數組)的“架子”分配內存。 因此,我為weatherp
結構體的n
實例分配了內存,然后,在使用fscanf(3)
我分別為每個結構體字段分配了內存。 畢竟,由malloc(3)
分配的malloc(3)
應該通過使用free(3)
(每個結構域和最后——結構實例的容器malloc(3)
來釋放。
最后一個函數fourth_option()定義了結構的兩元素數組(定義為weather
類型),但結構的字段沒有分配內存。 因此,在使用fscanf(3)
我分別為每個 struct 字段分配內存。 畢竟, malloc(3)
分配的malloc(3)
應該使用free(3)
釋放。
一些額外的信息:
聲明為int a;
變量的每個地址int a;
, struct type name;
或char tab[10];
已經在堆棧上動態分配了內存,並且該內存在函數結束后自動“釋放”。 手動分配的空間(例如使用malloc(3)
)在堆上分配,直到調用free(3)
函數。 如今,程序結束后的操作系統內核可以釋放手動分配的內存,但消除內存泄漏是一種很好的做法,它表明您知道自己在做什么。
附注。 在測試期間,我將月數從 12 替換為 2 並從stdin
讀取數據,而不是從文件中讀取數據。 當然,我們應該檢查諸如成功執行函數之類的事情(例如,如果malloc(3)
調用后的指針不是NULL
)。 我只是不想使代碼復雜化。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.