質問するログイン新規登録

回答編集履歴

1

m

2020/11/18 17:45

投稿

yumetodo
yumetodo

スコア5852

answer CHANGED
@@ -46,4 +46,136 @@
46
46
  UndefinedBehaviorSanitizer: nested bug in the same thread, aborting.
47
47
  ```
48
48
 
49
- のように結果が得られます。つまり、全般に配列へのアクセスに問題があります。
49
+ のように結果が得られます。つまり、全般に配列へのアクセスに問題があります。
50
+
51
+
52
+ 多少書き直してデバッグログも仕込んでみました
53
+
54
+ ```c
55
+ #include <stdio.h>
56
+ #include <stdlib.h>
57
+ #include <string.h>
58
+
59
+ #define N 50
60
+
61
+ struct LOG {
62
+ long time;
63
+ char server_name[N];
64
+ char result[N];
65
+ };
66
+
67
+ void printTime(long kikan) {
68
+ char kikan2[14];
69
+ sprintf(kikan2, "%ld", kikan);
70
+ int len = strlen(kikan2);
71
+ long sec, min, hour, day, month, year;
72
+ year = kikan / 10000000000;
73
+ month = (kikan / 1000000) % 100;
74
+ day = (kikan / 10000) % 100;
75
+ hour = (kikan / 100) % 100;
76
+ min = kikan / 100;
77
+ sec = kikan % 100;
78
+
79
+ if (len <= 2) {
80
+ printf("故障期間は%ld秒です\n", sec);
81
+ } else if (len <= 4) {
82
+ printf("故障期間は%ld分%ld秒です\n", min, sec);
83
+ } else if (len <= 6) {
84
+ printf("故障期間は%ld時%ld分%ld秒です\n", hour, min, sec);
85
+ } else if (len <= 8) {
86
+ printf("故障期間は%ld日%ld時%ld分%ld秒です\n", day, hour, min, sec);
87
+ } else if (len <= 10) {
88
+ printf("故障期間は%ld月%ld日%ld時%ld分%ld秒です\n", month, day, hour, min, sec);
89
+ } else if (len <= 14) {
90
+ printf("故障期間は%ld年%ld月%ld日%ld時%ld分%ld秒です\n", year, month, day, hour, min, sec);
91
+ }
92
+ }
93
+
94
+ int main() {
95
+ FILE *fp;
96
+ struct LOG log[30];
97
+
98
+ char s[N][N], *cp, handan_name[N];
99
+
100
+ const char *sikiri = ",";
101
+ long handan_time = 0, kikan;
102
+ int i = 0, len = 0, ct = 0; // ctによって一度のエラーにつき一回のみと判断
103
+
104
+ fp = fopen("server.txt", "r");
105
+
106
+ while (fgets(s[i], N, fp) != NULL) {
107
+ printf("Debug(line %d): i=%d\n", __LINE__, i);
108
+ cp = strtok(s[i], sikiri);
109
+ log[i].time = atol(cp); //ここで時間を挿入、文字列から数に変換
110
+ int c = 0;
111
+ while (NULL != (cp = strtok(NULL, sikiri))) {
112
+ if (c == 0) {
113
+ strcpy(log[i].server_name, cp); //ここでサーバーの名前を挿入
114
+ c++;
115
+
116
+ if (strcmp(&handan_name[len - 1], "1") && strncmp(handan_name, log[i].server_name, 8) == 0 &&
117
+ ct == 1) { // if(故障していたら)ここでサーバーの名前がかぶってないか判断
118
+ kikan = log[i].time - handan_time;
119
+ printTime(kikan);
120
+ ct--;
121
+ } else if (strcmp(&handan_name[len - 1], "2") && strncmp(handan_name, log[i].server_name, 9) == 0 && ct == 1) {
122
+ kikan = log[i].time - handan_time;
123
+ printTime(kikan);
124
+ ct--;
125
+ }
126
+ }
127
+
128
+ if (cp != NULL && c == 1) {
129
+ strcpy(log[i].result, cp); //ここで結果を挿入
130
+ if (strncmp(log[i].result, "-", 1) == 0 && ct == 0) {
131
+ printf("サーバー%sが故障状態です\n", log[i].server_name); //サーバーが故障しているか判断
132
+ len = strlen(log[i].server_name);
133
+ handan_time = log[i].time;
134
+ strcpy(handan_name, log[i].server_name);
135
+ ct++;
136
+ }
137
+ }
138
+ }
139
+ i++;
140
+ }
141
+
142
+ fclose(fp);
143
+ return 0;
144
+ }
145
+ ```
146
+
147
+ 同様に実行すると
148
+
149
+ ```
150
+ Debug(line 53): i=0
151
+ main.cpp:62:21: runtime error: index -1 out of bounds for type 'char [50]'
152
+ SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior main.cpp:62:21 in
153
+ main.cpp:67:28: runtime error: index -1 out of bounds for type 'char [50]'
154
+ SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior main.cpp:67:28 in
155
+ Debug(line 53): i=1
156
+ Debug(line 53): i=2
157
+ Debug(line 53): i=3
158
+ Debug(line 53): i=4
159
+ Debug(line 53): i=5
160
+ Debug(line 53): i=6
161
+ Debug(line 53): i=7
162
+ Debug(line 53): i=8
163
+ サーバー10.20.30.1/16が故障状態です
164
+ Debug(line 53): i=9
165
+ 故障期間は1秒です
166
+ Debug(line 53): i=10
167
+ サーバー10.20.30.1/16が故障状態です
168
+ Debug(line 53): i=11
169
+ 故障期間は7分6秒です
170
+ Debug(line 53): i=12
171
+ サーバー10.20.30.1/16が故障状態です
172
+ Debug(line 53): i=13
173
+ 故障期間は10秒です
174
+ Debug(line 53): i=14
175
+ サーバー192.168.1.1/24が故障状態です
176
+ Debug(line 53): i=15
177
+ 故障期間は5分90秒です
178
+ Debug(line 53): i=16
179
+ ```
180
+
181
+ 56行目で初期化されている変数`c`に着目すると、`c`が0となるのは初めてループに入ったときのみとなります。このとき`len`は確実に`0`です。にも関わらす`len -1`のようにアクセスしているため、配列外参照になっています。これは多分ロジックがおかしいのではないのですかね。