runtime_checks

/RTC选项用于启用和禁用运行时错误检查功能,包括数据损失检测、堆栈帧验证及未初始化变量使用的报告等。这些检查有助于在开发过程中发现代码中的潜在问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/RTC (Run-Time Error Checks)


Used to enable and disable the run-time error checks feature, in conjunction with the runtime_checks pragma.

/RTC1
/RTCc
/RTCs
/RTCu

1

Equivalent of /RTCsu.

c

Reports when a value is assigned to a smaller data type and results in a data loss. For example, if a value of type short 0x101 is assigned to a variable of type char.

This option reports situations in which you intend to truncate, for example, if you want the first eight bits of an int returned as a char. Because /RTCc causes a run-time error if any information is lost as a result of the assignment, you can mask off the information you need to avoid a run-time error as a result of /RTCc. For example:

#include <crtdbg.h>

char get8bits(int value, int position) {
   _ASSERT(position < 32);
   return (char)(value >> position);
   // Try the following line instead:
   // return (char)((value >> position) & 0xff);
}

int main() {
   get8bits(12341235,3);
}
s

Enables stack frame run-time error checking, as follows:

  • Initialization of local variables to a nonzero value. This helps identify bugs that do not appear when running in debug mode. There is a greater chance that stack variables will still be zero in a debug build compared to a release build because of compiler optimizations of stack variables in a release build. Once a program has used an area of its stack, it is never reset to 0 by the compiler. Therefore, subsequent, uninitialized stack variables that happen to use the same stack area can return values left over from the prior use of this stack memory.

  • Detection of overruns and underruns of local variables such as arrays. /RTC s will not detect overruns when accessing memory that results from compiler padding within a structure.Padding could occur by using align (C++)/Zp (Struct Member Alignment), or pack, or if you order structure elements in such a way as to require the compiler to add padding.

  • Stack pointer verification, which detects stack pointer corruption. Stack pointer corruption can be caused by a calling convention mismatch. For example, using a function pointer, you call a function in a DLL that is exported as __stdcall but you declare the pointer to the function as__cdecl.

u

Reports when a variable is used without having been initialized. For example, an instruction that generates C4701 may also generate a run-time error under /RTCu. Any instruction that generatesCompiler Warning (level 1 and level 4) C4700 will generate a run-time error under /RTCu.

However, consider the following code fragment:

int a, *b, c;
if ( 1 )
b = &a;
c = a;  // No run-time error with /RTCu

If a variable could have been initialized, it will not be reported at run time by /RTCu. For example, after a variable is aliased through a pointer, the compiler will not track the variable and report uninitialized uses. In effect, you can initialize a variable by taking its address. The & operator works like an assignment operator in this situation.

Run-time error checks are a way for you to find problems in your running code; for more information, seeHow to: Use Native Run-Time Checks.

If you compile your program at the command line using any of the /RTC compiler options, any pragmaoptimize instructions in your code will silently fail. This is because run-time error checks are not valid in a release (optimized) build.

You should use /RTC for development builds; /RTC should not be used for a retail build. /RTC cannot be used with compiler optimizations (/O Options (Optimize Code)). A program image built with /RTC will be slightly larger and slightly slower than an image built with /Od (up to 5 percent slower than an /Od build).

The __MSVC_RUNTIME_CHECKS preprocessor directive will be defined when you use any /RTC option or /GZ.

To set this compiler option in the Visual Studio development environment

  1. Open the project's Property Pages dialog box. For details, see How to: Open Project Property Pages.

  2. Click the C/C++ folder.

  3. Click the Code Generation property page.

  4. Modify one or both of the following properties: Basic Runtime Checks or Smaller Type Check.

To set this compiler option programmatically

runtime_checks


Disables or restores the /RTC settings.

#pragma runtime_checks( "[runtime_checks]", {restore | off} )

You cannot enable a run-time check that was not enabled with a compiler option. For example, if you do not specify /RTCs, specifying #pragma runtime_checks( "s", restore) will not enable stack frame verification.

The runtime_checks pragma must appear outside a function and takes effect at the first function defined after the pragma is seen. The restore and off arguments turn options specified in the runtime_checks on or off.

The runtime_checks can be zero or more of the parameters shown in the following table.

Parameters of the runtime_checks Pragma

Parameter(s)

Type of run-time check

s

Enables stack (frame) verification.

c

Reports when a value is assigned to a smaller data type that results in a data loss.

u

Reports when a variable is used before it is defined.

These are the same letters used with the /RTC compiler option. For example:

#pragma runtime_checks( "sc", restore )

Using the runtime_checks pragma with the empty string ("") is a special form of the directive:

  • When you use the off parameter, it turns the run-time error checks, listed in the table above, off.

  • When you use the restore parameter, it resets the run-time error checks to those that you specified with the /RTC compiler option.

#pragma runtime_checks( "", off )
.
.
.
#pragma runtime_checks( "", restore ) 
boolean isIndexDataFromSettingsAndOtherSuccess() { 1. thread1_checks_field: Thread1 uses the value read from static field mCollector in the condition com.android.settings.intelligence.search.indexing.DatabaseIndexingManager.mCollector == null. It sees that the condition is true. CID 205394: (#1 of 1): Check of thread-shared field evades lock acquisition (LOCK_EVASION) 5. thread2_checks_field_early: Thread2 checks mCollector, reading it after Thread1 assigns to mCollector but before some of the correlated field assignments can occur. It sees the condition com.android.settings.intelligence.search.indexing.DatabaseIndexingManager.mCollector == null as being false. It continues on before the critical section has completed, and can read data changed by that critical section while it is in an inconsistent state. Remove this outer, unlocked check of mCollector. 199 if (mCollector == null) { 2. thread1_acquires_lock: Thread1 acquires lock com.android.settings.intelligence.search.indexing.DatabaseIndexingManager.INDEX_SEARCH_OBJECT. 200 synchronized (INDEX_SEARCH_OBJECT) { 3. thread1_double_checks_field: Thread1 double checks the static field mCollector in the condition com.android.settings.intelligence.search.indexing.DatabaseIndexingManager.mCollector == null. 201 if (mCollector == null) { 4. thread1_modifies_field: Thread1 modifies the static field mCollector. This modification can be re-ordered with other correlated field assignments within this critical section at runtime. Thus, checking the value of mCollector is not an adequate test that the critical section has completed unless the guarding lock is held while checking. If mCollector is assigned a newly constructed value, note that the JVM is allowed to reorder the assignment of the new reference to mCollector before any field assignments that may occur in the constructor. Control is switched to Thread2.
06-27
int main(int argc, char *argv[]) { dual_timestamp initrd_timestamp = DUAL_TIMESTAMP_NULL, userspace_timestamp = DUAL_TIMESTAMP_NULL, kernel_timestamp = DUAL_TIMESTAMP_NULL, security_start_timestamp = DUAL_TIMESTAMP_NULL, security_finish_timestamp = DUAL_TIMESTAMP_NULL; struct rlimit saved_rlimit_nofile = RLIMIT_MAKE_CONST(0), saved_rlimit_memlock = RLIMIT_MAKE_CONST(RLIM_INFINITY); /* The original rlimits we passed * in. Note we use different values * for the two that indicate whether * these fields are initialized! */ bool skip_setup, loaded_policy = false, queue_default_job = false, first_boot = false; char *switch_root_dir = NULL, *switch_root_init = NULL; usec_t before_startup, after_startup; static char systemd[] = "systemd"; const char *error_message = NULL; uint64_t saved_ambient_set = 0; int r, retval = EXIT_FAILURE; Manager *m = NULL; FDSet *fds = NULL; assert_se(argc > 0 && !isempty(argv[0])); /* Take timestamps early on */ dual_timestamp_from_monotonic(&kernel_timestamp, 0); dual_timestamp_now(&userspace_timestamp); /* Figure out whether we need to do initialize the system, or if we already did that because we are * reexecuting. */ skip_setup = early_skip_setup_check(argc, argv); /* If we get started via the /sbin/init symlink then we are called 'init'. After a subsequent * reexecution we are then called 'systemd'. That is confusing, hence let's call us systemd * right-away. */ program_invocation_short_name = systemd; (void) prctl(PR_SET_NAME, systemd); /* Save the original command line */ save_argc_argv(argc, argv); /* Save the original environment as we might need to restore it if we're requested to execute another * system manager later. */ r = save_env(); if (r < 0) { error_message = "Failed to copy environment block"; goto finish; } /* Make sure that if the user says "syslog" we actually log to the journal. */ log_set_upgrade_syslog_to_journal(true); if (getpid_cached() == 1) { /* When we run as PID 1 force system mode */ arg_runtime_scope = RUNTIME_SCOPE_SYSTEM; /* Disable the umask logic */ umask(0); /* Make sure that at least initially we do not ever log to journald/syslogd, because it might * not be activated yet (even though the log socket for it exists). */ log_set_prohibit_ipc(true); /* Always reopen /dev/console when running as PID 1 or one of its pre-execve() children. This * is important so that we never end up logging to any foreign stderr, for example if we have * to log in a child process right before execve()'ing the actual binary, at a point in time * where socket activation stderr/stdout area already set up. */ log_set_always_reopen_console(true); if (detect_container() <= 0) { /* Running outside of a container as PID 1 */ log_set_target_and_open(LOG_TARGET_KMSG); if (in_initrd()) initrd_timestamp = userspace_timestamp; if (!skip_setup) { r = mount_setup_early(); if (r < 0) { error_message = "Failed to mount early API filesystems"; goto finish; } } /* We might have just mounted /proc, so let's try to parse the kernel * command line log arguments immediately. */ log_parse_environment(); /* Let's open the log backend a second time, in case the first time didn't * work. Quite possibly we have mounted /dev just now, so /dev/kmsg became * available, and it previously wasn't. */ log_open(); if (!skip_setup) { disable_printk_ratelimit(); r = initialize_security( &loaded_policy, &security_start_timestamp, &security_finish_timestamp, &error_message); if (r < 0) goto finish; } r = mac_init(); if (r < 0) { error_message = "Failed to initialize MAC support"; goto finish; } if (!skip_setup) initialize_clock_timewarp(); clock_apply_epoch(/* allow_backwards= */ !skip_setup); /* Set the default for later on, but don't actually open the logs like this for * now. Note that if we are transitioning from the initrd there might still be * journal fd open, and we shouldn't attempt opening that before we parsed * /proc/cmdline which might redirect output elsewhere. */ log_set_target(LOG_TARGET_JOURNAL_OR_KMSG); } else { /* Running inside a container, as PID 1 */ log_set_target_and_open(LOG_TARGET_CONSOLE); /* For later on, see above... */ log_set_target(LOG_TARGET_JOURNAL); /* clear the kernel timestamp, because we are in a container */ kernel_timestamp = DUAL_TIMESTAMP_NULL; } initialize_coredump(skip_setup); r = fixup_environment(); if (r < 0) { log_struct_errno(LOG_EMERG, r, LOG_MESSAGE("Failed to fix up PID 1 environment: %m"), LOG_MESSAGE_ID(SD_MESSAGE_CORE_PID1_ENVIRONMENT_STR)); error_message = "Failed to fix up PID1 environment"; goto finish; } /* Try to figure out if we can use colors with the console. No need to do that for user * instances since they never log into the console. */ log_show_color(colors_enabled()); r = make_null_stdio(); if (r < 0) log_warning_errno(r, "Failed to redirect standard streams to /dev/null, ignoring: %m"); /* Load the kernel modules early. */ if (!skip_setup) (void) kmod_setup(); /* Mount /proc, /sys and friends, so that /proc/cmdline and /proc/$PID/fd is available. */ r = mount_setup(loaded_policy, skip_setup); if (r < 0) { error_message = "Failed to mount API filesystems"; goto finish; } /* The efivarfs is now mounted, let's lock down the system token. */ lock_down_efi_variables(); } else { /* Running as user instance */ arg_runtime_scope = RUNTIME_SCOPE_USER; log_set_always_reopen_console(true); log_set_target_and_open(LOG_TARGET_AUTO); /* clear the kernel timestamp, because we are not PID 1 */ kernel_timestamp = DUAL_TIMESTAMP_NULL; r = mac_init(); if (r < 0) { error_message = "Failed to initialize MAC support"; goto finish; } } /* Save the original RLIMIT_NOFILE/RLIMIT_MEMLOCK so that we can reset it later when * transitioning from the initrd to the main systemd or suchlike. */ save_rlimits(&saved_rlimit_nofile, &saved_rlimit_memlock); /* Reset all signal handlers. */ (void) reset_all_signal_handlers(); (void) ignore_signals(SIGNALS_IGNORE); (void) parse_configuration(&saved_rlimit_nofile, &saved_rlimit_memlock); r = parse_argv(argc, argv); if (r < 0) { error_message = "Failed to parse command line arguments"; goto finish; } r = safety_checks(); if (r < 0) goto finish; if (IN_SET(arg_action, ACTION_TEST, ACTION_HELP, ACTION_DUMP_CONFIGURATION_ITEMS, ACTION_DUMP_BUS_PROPERTIES, ACTION_BUS_INTROSPECT)) pager_open(arg_pager_flags); if (arg_action != ACTION_RUN) skip_setup = true; if (arg_action == ACTION_HELP) { retval = help() < 0 ? EXIT_FAILURE : EXIT_SUCCESS; goto finish; } else if (arg_action == ACTION_VERSION) { retval = version(); goto finish; } else if (arg_action == ACTION_DUMP_CONFIGURATION_ITEMS) { unit_dump_config_items(stdout); retval = EXIT_SUCCESS; goto finish; } else if (arg_action == ACTION_DUMP_BUS_PROPERTIES) { dump_bus_properties(stdout); retval = EXIT_SUCCESS; goto finish; } else if (arg_action == ACTION_BUS_INTROSPECT) { r = bus_manager_introspect_implementations(stdout, arg_bus_introspect); retval = r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE; goto finish; } assert_se(IN_SET(arg_action, ACTION_RUN, ACTION_TEST)); /* Move out of the way, so that we won't block unmounts */ assert_se(chdir("/") == 0); if (arg_action == ACTION_RUN) { if (!skip_setup) { /* Apply the systemd.clock_usec= kernel command line switch */ apply_clock_update(); /* Apply random seed from kernel command line */ cmdline_take_random_seed(); } /* A core pattern might have been specified via the cmdline. */ initialize_core_pattern(skip_setup); /* Make /usr/ read-only */ apply_protect_system(skip_setup); /* Close logging fds, in order not to confuse collecting passed fds and terminal logic below */ log_close(); /* Remember open file descriptors for later deserialization */ r = collect_fds(&fds, &error_message); if (r < 0) goto finish; /* Give up any control of the console, but make sure its initialized. */ setup_console_terminal(skip_setup); /* Open the logging devices, if possible and necessary */ log_open(); } log_execution_mode(&first_boot); r = cg_has_legacy(); if (r < 0) { error_message = "Failed to check cgroup hierarchy"; goto finish; } if (r > 0) { r = log_full_errno(LOG_EMERG, SYNTHETIC_ERRNO(EPROTO), "Detected cgroup v1 hierarchy at /sys/fs/cgroup/, which is no longer supported by current version of systemd.\n" "Please instruct your initrd to mount cgroup v2 (unified) hierarchy,\n" "possibly by removing any stale kernel command line options, such as:\n" " systemd.legacy_systemd_cgroup_controller=1\n" " systemd.unified_cgroup_hierarchy=0"); error_message = "Detected unsupported legacy cgroup hierarchy, refusing execution"; goto finish; } r = initialize_runtime(skip_setup, first_boot, &saved_rlimit_nofile, &saved_rlimit_memlock, &saved_ambient_set, &error_message); if (r < 0) goto finish; r = manager_new(arg_runtime_scope, arg_action == ACTION_TEST ? MANAGER_TEST_FULL : 0, &m); if (r < 0) { log_struct_errno(LOG_EMERG, r, LOG_MESSAGE("Failed to allocate manager object: %m"), LOG_MESSAGE_ID(SD_MESSAGE_CORE_MANAGER_ALLOCATE_STR)); error_message = "Failed to allocate manager object"; goto finish; } m->timestamps[MANAGER_TIMESTAMP_KERNEL] = kernel_timestamp; m->timestamps[MANAGER_TIMESTAMP_INITRD] = initrd_timestamp; m->timestamps[MANAGER_TIMESTAMP_USERSPACE] = userspace_timestamp; m->timestamps[manager_timestamp_initrd_mangle(MANAGER_TIMESTAMP_SECURITY_START)] = security_start_timestamp; m->timestamps[manager_timestamp_initrd_mangle(MANAGER_TIMESTAMP_SECURITY_FINISH)] = security_finish_timestamp; m->saved_ambient_set = saved_ambient_set; set_manager_defaults(m); set_manager_settings(m); manager_set_first_boot(m, first_boot); manager_set_switching_root(m, arg_switched_root); /* Remember whether we should queue the default job */ queue_default_job = !arg_serialization || arg_switched_root; before_startup = now(CLOCK_MONOTONIC); r = manager_startup(m, arg_serialization, fds, /* root= */ NULL); if (r < 0) { error_message = "Failed to start up manager"; goto finish; } /* This will close all file descriptors that were opened, but not claimed by any unit. */ fds = fdset_free(fds); arg_serialization = safe_fclose(arg_serialization); if (queue_default_job) { r = do_queue_default_job(m, &error_message); if (r < 0) goto finish; } after_startup = now(CLOCK_MONOTONIC); log_full(arg_action == ACTION_TEST ? LOG_INFO : LOG_DEBUG, "Loaded units and determined initial transaction in %s.", FORMAT_TIMESPAN(after_startup - before_startup, 100 * USEC_PER_MSEC)); if (arg_action == ACTION_TEST) { manager_test_summary(m); retval = EXIT_SUCCESS; goto finish; } r = invoke_main_loop(m, &saved_rlimit_nofile, &saved_rlimit_memlock, &retval, &fds, &switch_root_dir, &switch_root_init, &error_message); /* MANAGER_OK and MANAGER_RELOAD are not expected here. */ assert(r < 0 || IN_SET(r, MANAGER_REEXECUTE, MANAGER_EXIT) || (arg_runtime_scope == RUNTIME_SCOPE_SYSTEM && IN_SET(r, MANAGER_REBOOT, MANAGER_SOFT_REBOOT, MANAGER_POWEROFF, MANAGER_HALT, MANAGER_KEXEC, MANAGER_SWITCH_ROOT))); finish: pager_close(); if (m) { arg_reboot_watchdog = manager_get_watchdog(m, WATCHDOG_REBOOT); arg_kexec_watchdog = manager_get_watchdog(m, WATCHDOG_KEXEC); m = manager_free(m); } mac_selinux_finish(); if (IN_SET(r, MANAGER_REEXECUTE, MANAGER_SWITCH_ROOT, MANAGER_SOFT_REBOOT)) r = do_reexecute(r, argc, argv, &saved_rlimit_nofile, &saved_rlimit_memlock, fds, switch_root_dir, switch_root_init, saved_ambient_set, &error_message); /* This only returns if reexecution failed */ arg_serialization = safe_fclose(arg_serialization); fds = fdset_free(fds); saved_env = strv_free(saved_env); #if HAVE_VALGRIND_VALGRIND_H /* If we are PID 1 and running under valgrind, then let's exit * here explicitly. valgrind will only generate nice output on * exit(), not on exec(), hence let's do the former not the * latter here. */ if (getpid_cached() == 1 && RUNNING_ON_VALGRIND) { /* Cleanup watchdog_device strings for valgrind. We need them * in become_shutdown() so normally we cannot free them yet. */ watchdog_free_device(); reset_arguments(); return retval; } #endif #if HAS_FEATURE_ADDRESS_SANITIZER /* At this stage we most likely don't have stdio/stderr open, so the following * LSan check would not print any actionable information and would just crash * PID 1. To make this a bit more helpful, let's try to open /dev/console, * and if we succeed redirect LSan's report there. */ if (getpid_cached() == 1) { _cleanup_close_ int tty_fd = -EBADF; tty_fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC); if (tty_fd >= 0) __sanitizer_set_report_fd((void*) (intptr_t) tty_fd); __lsan_do_leak_check(); } #endif if (r < 0) (void) sd_notifyf(/* unset_environment= */ false, "ERRNO=%i", -r); /* Try to invoke the shutdown binary unless we already failed. * If we failed above, we want to freeze after finishing cleanup. */ if (arg_runtime_scope == RUNTIME_SCOPE_SYSTEM && IN_SET(r, MANAGER_EXIT, MANAGER_REBOOT, MANAGER_POWEROFF, MANAGER_HALT, MANAGER_KEXEC)) { r = become_shutdown(r, retval); log_error_errno(r, "Failed to execute shutdown binary, %s: %m", getpid_cached() == 1 ? "freezing" : "quitting"); error_message = "Failed to execute shutdown binary"; } /* This is primarily useful when running systemd in a VM, as it provides the user running the VM with * a mechanism to pick up systemd's exit status in the VM. */ (void) sd_notifyf(/* unset_environment= */ false, "EXIT_STATUS=%i", retval); watchdog_free_device(); arg_watchdog_device = mfree(arg_watchdog_device); if (getpid_cached() == 1) { if (error_message) manager_status_printf(NULL, STATUS_TYPE_EMERGENCY, ANSI_HIGHLIGHT_RED "!!!!!!" ANSI_NORMAL, "%s.", error_message); freeze_or_exit_or_reboot(); } reset_arguments(); return retval; } 这段是systemd的主函数,请你详细讲解、梳理一下
最新发布
08-04
{ "file_identification": { "program_name": "程序运动1", "description": "走直线程序", "created_time": "2025-07-09T14:30:22Z" }, "program_execution": { "operation_controls": { "start_command": "python main_program.py --start", "stop_command": "python main_program.py --stop", "restart_command": "python main_program.py --restart", "execution_mode": "automatic", "priority_level": 3 }, "runtime_parameters": { "input_source": "/data/input/user_data.csv", "output_destination": "/data/output/processed_data_20250709_143022.json", "processing_options": { "enable_filtering": true, "data_validation": true, "generate_summary": true, "compress_output": false }, "timeout_seconds": 1800, "retry_attempts": 3 }, "status_monitoring": { "current_status": "running", "progress_percentage": 65.8, "start_time": "2025-07-09T14:30:25Z", "estimated_completion": "2025-07-09T14:45:30Z", "error_logs": [ { "timestamp": "2025-07-09T14:32:15Z", "level": "warning", "message": "数据行1523格式异常,已跳过处理" } ] }, "data_operations": { "read_operations": [ { "operation_type": "csv_read", "file_path": "/data/input/user_data.csv", "encoding": "utf-8", "rows_processed": 12580 } ], "write_operations": [ { "operation_type": "json_write", "file_path": "/data/output/processed_data_20250709_143022.json", "encoding": "utf-8", "format_options": { "indent": 2, "ensure_ascii": false } } ], "transform_operations": [ "数据清洗", "格式标准化", "重复项去除", "统计计算" ], "validation_rules": { "required_fields": ["id", "name", "timestamp"], "data_types": { "id": "integer", "name": "string", "timestamp": "datetime" }, "range_checks": { "id": {"min": 1, "max": 999999} } }, "backup_settings": { "enable_backup": true, "backup_interval": 300, "backup_location": "/data/backup/" } }, "performance_metrics": { "cpu_usage": 23.5, "memory_usage": 145.7, "execution_duration": 892.3, "throughput_rate": 14.1, "success_rate": 98.8 } } } 这样的格式昨晚文件保存的内容 可以吗
07-10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值