可変長文字列を印刷しようとするとセグメント違反が発生します。 printfまたはログファイルで文字列を出力すると、文字列が正常に印刷されます。別の問題は、同じテストが別のマシンでうまく動作するマシンでのみクラッシュが発生していることです。なぜ私は本当に混乱しています。文字列を印刷しようとするとSegフォールトが発生する
編集:クラッシュを引き起こしている完全な作業コード私は下に貼り付けています。 クラッシュはCentos 6.3とCentos 6.5で発生します。クラッシュは、次の
#include <stdio.h>
#include <stdarg.h>
#include <stdint.h>
#include <sys/time.h>
#include <time.h>
typedef struct {
uint64_t total_bytes_sent;
uint64_t total_bytes_received;
uint64_t total_blocks_sent;
uint64_t total_blocks_received;
uint64_t total_commands_sent;
uint64_t total_commands_received;
uint64_t time_to_process_data;
char mark_sent_time[64];
char mark_received_time[64];
} csperf_stats_t;
void
csperf_stats_printf(const char *format, ...)
{
/* Write to file */
va_list args;
/* Write to stdout */
va_start(args, format);
vfprintf(stdout, format, args);
va_end(args);
}
void
ansperf_stats_display(csperf_stats_t *stats)
{
if (!stats) {
return;
}
stats->total_blocks_sent = 1000;
stats->total_blocks_received = 2000;
stats->time_to_process_data = 22;
csperf_stats_printf("%3d %15s %10s %10zu %10zu %10zu %10s "
"%10s\n\n",
0, "hi", "testing.",
stats->total_blocks_sent, stats->total_blocks_received,
stats->time_to_process_data,
"crash", "test");
}
/* Get time in millisecond */
uint64_t
csperf_network_get_time(char *buf)
{
char fmt[64];
struct tm *tm;
struct timeval tv;
uint64_t s;
gettimeofday(&tv, NULL);
if (buf) {
if((tm = localtime(&tv.tv_sec)) != NULL) {
strftime(fmt, sizeof(fmt), "%Y-%m-%d %H:%M:%S.%03u", tm);
snprintf(buf, sizeof(fmt), fmt, tv.tv_usec);
}
}
s = tv.tv_sec * 1000LL;
return(s + tv.tv_usec/1000LL);
}
int main()
{
csperf_stats_t stats = { 0 };
csperf_network_get_time(stats.mark_sent_time);
csperf_network_get_time(stats.mark_received_time);
printf("%s%s\n", stats.mark_sent_time, stats.mark_received_time);
ansperf_stats_display(&stats);
}
CentOSに5では見られないことは、それがクラッシュしたコードスニペットです。
stats-> mark_sent_time、stats-> mark_received_timeを印刷しようとすると、vfprintf()がクラッシュします。文字列をgdbに表示すると、文句はありません。
command->echo_timestamp = csperf_network_get_time(
client->stats.mark_sent_time);
:
void
csperf_stats_printf(FILE *fd, const char *format, ...)
{
/* Write to file */
va_list args;
va_start(args, format);
if (fd) {
vfprintf(fd, format, args);
}
va_end(args);
/* Write to stdout */
va_start(args, format);
vfprintf(stdout, format, args);
va_end(args);
}
void
ansperf_stats_display(csperf_stats_t *stats, FILE *fd)
{
static int header_displayed = 0;
static int cycle = 0;
char total_bytes_sent_str[50];
char total_bytes_recv_str[50];
if (!stats) {
return;
}
if (!header_displayed) {
csperf_stats_printf(fd, "%s%s", header, seperator_line);
header_displayed = 1;
}
csperf_common_calculate_size(total_bytes_sent_str,
stats->total_bytes_sent);
csperf_common_calculate_size(total_bytes_recv_str,
stats->total_bytes_received);
csperf_stats_printf(fd, "%3d %15s %10s %10zu %10zu %10zu %10s "
"%10s\n\n", ++cycle,
total_bytes_sent_str, total_bytes_recv_str,
stats->total_blocks_sent, stats->total_blocks_received,
stats->time_to_process_data,
stats->mark_sent_time, stats->mark_received_time);
}
これは
char mark_sent_time[100];
char mark_received_time[100];
それは次のように設定され、次のように文字列は100バイトの配列であるGDBが
(gdb) p stats->mark_sent_time
No symbol "stats" in current context.
(gdb) f 2
#2 0x08051f56 in ansperf_stats_display (stats=0x892ded4, fd=0x892e888) at /home/nikhil/csperf/src/csperf_stats.c:55
55 csperf_stats_printf(fd, "%3d %15s %10s %10zu %10zu %10zu %100s "
(gdb) p stats->mark_sent_time
$1 = "20160821 21325800007", '\000' <repeats 79 times>
(gdb) p stats->mark_recei9ved_time
There is no member named mark_recei9ved_time.
(gdb) p stats->mark_received_time
$2 = "20160821 21325800007", '\000' <repeats 79 times>
を示すものですこの関数はタイムスタンプをstrinにコピーします。グラム "mark_sent_time"
uint64_t
csperf_network_get_time(char *buf)
{
char fmt[64];
struct tm *tm;
struct timeval tv;
uint64_t s;
gettimeofday(&tv, NULL);
if (buf) {
if((tm = localtime(&tv.tv_sec)) != NULL) {
strftime(fmt, sizeof(fmt), "%Y-%m-%d %H:%M:%S.%03u", tm);
snprintf(buf, sizeof(fmt), fmt, tv.tv_usec);
}
}
s = tv.tv_sec * 1000LL;
return(s + tv.tv_usec/1000LL);
}
バックトレース:
(gdb) bt
#0 0x002b535e in _IO_vfprintf_internal (s=Cannot access memory at address 0xffffffff
) at vfprintf.c:1603
#1 0x08051de7 in csperf_stats_printf (fd=0x892e888, format=0x8079a6c "%3d %15s %10s %10zu %10zu %10zu %100s %100s \n\n") at /home/nikhil/csperf/src/csperf_stats.c:23
#2 0x08051f56 in ansperf_stats_display (stats=0x892ded4, fd=0x892e888) at /home/nikhil/csperf/src/csperf_stats.c:55
#3 0x08050ad3 in csperf_client_shutdown (client=0x892deb0) at /home/nikhil/csperf/src/csperf_client.c:67
私は何をしないのですか?
問題を再現するのに十分なコードを教えていただけますか?おそらく 'FILE * 'が無効です。 –
ファイルに印刷するコードを削除しましたが、次のvprintfでstdoutに印刷しようとするとクラッシュします – Nikhil
そのテストを自分で複製できれば、問題を見つけ出すことができます。 –