#include <stdio.h> int main(int argc argv 用法, char const *argv[]) { int array[3][2]={1,2,3,4,5,6};

linux 我有2个c程序 a,b 是否可以通过获得a的物理地址之后,在b中调用a的函数?
被这个鸟问题困扰了1天...&br&鼓起勇气向各位大神请教一下...&br&不要喷我...&br&&br&a.c&br&#include &stdio.h&&br&&br&void sayHello()&br&{&br& printf(&hello zhihu...\n&);&br&}&br&&br&int main(int argc, char const *argv[])&br&{&br&&br& while(1);&br& return 0;&br&}&br&&br&nm a.out&br&拿到sayHello的虚拟地址 0x1234&br&&br&问题1:&br&是否可以通过pid 和 0x1234 算出sayHello 函数真正的物理地址addr&br&这里我百度了,可以通过proc下面的某个结点算?现在没有linux环境没办法测试&br&引申的另外一个问题就是,在用户态是否有权限?&br&&br&问题2:&br&是否可以另起一个进程&br&b.c, 通过addr来访问a中的sayHello函数&br&&br&谢谢各位大神...我真的不是一个伸手党...&br&不要让我滚去百度知道...&br&&br&----------------------&br&提出这个问题是由于在项目中,有一个服务在跑,经常会加一些功能,想在服务运行的时候测试一下对应函数调用的效果&br&正常的方法应该是写一个client通过进程间通信,发送字符串给服务,然后通过映射表来调用.&br&如果不能通过物理地址的方法来实现,只能按照正常的方法来写了&br&&br&---------------------&br&过节比较忙,这几天一直没上来...&br&首先非常感谢大家的回答!!&br&经过几位大神的提醒,用了ptrace这个函数&br&&br&今天晚上的测试 从12点搞到现在(我太弱了)&br&在b.c里面用ptrace 可以实现跨进程的访问&br&这个貌似就是GDB的原理&br&可以先通过PTRACE_GETREGS 拿到一个a的寄存器信息 struct user_regs_struct&br&(这里比较有搞笑的地方是 结构体的头文件里面的注释 哈哈)&br&/* The whole purpose of this file is for GDB and GDB only.
Don't read&br&
too much into it.
Don't use it for anything other than GDB unless&br&
you know what you are doing.
*/&br&通过b设置好各项寄存器只会, PTRACE_SETREGSS回去,改变a的调用流程&br&比较经典的流程是,创建一个so,通过ptrace 注入到a里面,流程比较复杂 网上也有一些文章可以参考&br&&br&写一个最简单的一个例子就是 通过b来直接改a的全局变量&br&a:&br&#include&stdio.h&&br&#include&unistd.h&&br&&br&int main(int argc, char const *argv[])&br&{&br&printf(&pid : %d\n&,getpid());&br&var=0;&br&while(var!=1);&br&printf(&end...%d&,var);&br&}&br&gcc 编译之后 nm a.out |grep var &br&拿到虚拟地址 var的 &br&运行./a拿到pid 6498&br&&br&b:&br&#include &sys/ptrace.h&&br&#include &unistd.h&&br&#include &stdlib.h&&br&#include &stdio.h&&br&#include &sys/wait.h&&br&int main(int argc,char *argv[]) &br&{&br&pid_t traced_&br&&br&traced_process=atoi(argv[1]);&br&ptrace(PTRACE_ATTACH,traced_process,NULL,NULL);&br&wait(NULL);&br&data=ptrace(PTRACE_PEEKDATA,traced_process,0x);&br&printf(&data=%d\n&,data);&br&data=1;&br&ptrace(PTRACE_POKEDATA,traced_process,0x,data);&br&ptrace(PTRACE_DETACH,traced_process,0,0);&br&return 0;&br&}&br&sudo ./b 6498&br&a进程退出
被这个鸟问题困扰了1天...鼓起勇气向各位大神请教一下...不要喷我...a.c#include &stdio.h&void sayHello(){ printf("hello zhihu...\n");}int main(int argc, char const *argv[]){ while(1); return 0;}nm a.out…
按投票排序
第一,我先告诉你为什么不能。第二,我再告诉你怎样才能。第三,你现在明白很多程序员都是精神病患者了吧。不能,因为如果可以的话,任何一个程序,都可以闯入其他程序去调用一把,如同任何人都可以闯入他人的卧室和人家老婆来一发一样,少年郎,这样会乱套的!另外程序运行在虚拟地址空间,物理地址可能是支离破碎的。没鸟用。多任务操作系统用尽一切手段就是来隔离各个进程使其不受影响。怎样才能,大概有两种办法,第一种是合法手段获得对方程序授权,比如你说的写个client是最简单的一种。第二种是强行闯入,通过检查对方程序的错误,使用“缓冲区溢出”的方式,向对方程序注入代码(请自行百度)。但是第二种不一定能成功。请注意两种办法都是在对方的进程空间执行。作为一个精神病患者,能还是不能,其实并不是个问题,关键是为什么要这样?对于楼主的问题可能有另外一个解决办法是,把服务变成一个程序集即可。正常情况下a服务程序,有时会调用一下b程序(就是直接运行那种)测试的时候,c程序也来调用一下b程序。这样b就是一个公共的单身女青年了。
/proc/[pid]/maps
/proc/[pid]/pagemap
可以看到映射关系2.不行以下内容摘自《深入理解计算机系统》目标文件有三种形式:可重定位目标文件。包含二进制代码和数据,其形式可以在编译时与其他可重定位目标文件合并起来,创建一个可执行目标文件。可执行目标文件。包含二进制代码和数据,其形式可以被直接拷贝到存储器并执行。共享目标文件。一种特殊类型的可重定位目标文件,可以在加载或运行时被动态的加载到存储器并链接。编译器和汇编器生成可重定位目标文件(包括共享目标文件)。链接器生成可执行目标文件。简单来说,生成的 .o 文件就是可重定位目标文件。可以直接运行的自然是可执行目标文件。而 .so .ko 则都是共享目标文件。要得到共享目标文件,必须在编译时使用额外的参数来生成与位置无关的代码( Position-Independent Code , PIC)。所谓位置无关代码,就是说生成的二进制代码中的地址都是相对位置,这些相对位置在实际加载时会被加上一个全局偏移量产生绝对地址。所以, a.out 已经是链接过的可执行目标文件,不再具有重定位能力,二进制代码中的地址已经被硬编码成固定的值,即使你得到了函数的物理地址,你也无法通过这个物理地址来调用这个函数。
进程间地址空间是隔离的。
Windows在十几年前就有自动化技术(Automation)可以完美地从一个进程里调用到另一个自动化服务器进程里的函数,通过RPC。linux并没有这样的通信,通常进程间交互通过unix socket, pipe, shared memory完成。相比于Windows的做法,需要程序员自己考虑的东西多一些。
不是非常明白你的需求。如果是指一个已经载入内存运行的程序 a.c ,你想在 b.c 中调用它的某个函数,这有办法做到,但非常 tricky 也非常危险。RPC之类的解决方案,其它答主都提过了,我就不啰嗦了。如果不是这种需求,那双方配合一下,也行的:把程序当作动态库载入就是了。有一点小困难就是,这种手法在 Windows 下是没有任何问题的,只要函数本身被导出(用 DEF 文件或 __declspec(dllexport) 都行),那么就可以用 LoadLibrary 载入程序,用 GetProcAddr 取得函数入口。但是,在 Linux 是有点困难的——因为,ELF 文件格式对它的虚拟地址是有特定要求的,所以即使载入了也无法正常运行。不过,我们可以用 PIE 格式,所以,就有了下面的方法。不好意思我习惯用 C++,不过这个程序这么简单,用啥都一样。举个栗子:a.cpp 的代码------------------------- 以下是代码 --------------------------#include &iostream&// 注意用 extern "C" 来阻止名称 mangled。// 如果不这样,可以通过 nm 命令来找到确切的名称。(作死么?)extern "C" int __attribute__((dllexport)) addFunc(int a) {return a + 4;}int main() {std::cout && "result : " && addFunc(5);}------------------------- 以上是代码 --------------------------b.cpp 的代码------------------------- 以下是代码 --------------------------include &dlfcn.h&#include &iostream&typedef int __attribute__((dllimport)) (*AddFunc)(int a);int main() {void* hdl = dlopen("./dlhost", RTLD_NOW);if(!hdl) {cerr && "Load module fail : " && dlerror() &&return -1;}AddFunc addFunc = reinterpret_cast&AddFunc&(dlsym(hdl, "addFunc"));if(!addFunc) {cerr && "Load symbol fail" && dlerror() &&return -2;}cout && "result : " && addFunc(5) &&dlclose(hdl);}------------------------- 以上是代码 --------------------------下面是关键,我们要把 a.cpp 编译为 PIE 格式,并引出动态符号:g++ -o dlhost -fPIE a.cpp -pie -rdynamic至于 b.cpp ,就随便了,记得把 dl 库引入就行:g++ -o dlclient b.cpp -ldl然后运行验证一下:./dlclientresult : 9正确。不过:必须警告一下,PIE格式虽然允许这样载入,但作为一个可执行程序,如果这个函数对于 main 中的某些初始化操作有依赖,那就危险了:因为此时 a.cpp 中的 main 没有运行。
不能。如果我没记错的话,一个程序里的地址是系统分配给它特有的。也就是说,对于进程A里的地址0x1234这个物理存储空间来说,从另一个进程看它的话就不是0x1234了。题主可以考虑把你想共享的东西做成链接文件,然后在你需要的地方导入链接文件即可。另外,题主可以百度:进程间共享内存。这或许是你想要的。我只能让你百度看看了因为我也没做过。
不熟悉 Linux 平台。给个 OS X 平台上解决问题的思路供参考。首先需要明确一点就是调用的结果可以通过 Log 等看出来,而不需要再回传 b.out,否则直接用 RPC 就可以了。在这个前提下,问题就是能否通过 b.out 在 a.out 中实现代码注入。1、只要进程 b
对进程 a 有控制权,通过进程 b 向进程 a 注入代码就可以实现。2、故意在 a 程序中留个漏洞(后门),b 利用这个漏洞实现代码执行。在正常的开发中没必要用这些,基于 RPC 建立个相应的机制挺好的。另,问题中的物理地址让强迫症患者看起来很别扭,那只是加载后的地址,并不是什么物理地址。
注入进去是可以的
已有帐号?
无法登录?
社交帐号登录Create a two-dimensional array at runtime - Rosetta Codegetopt(3) - Linux man page
getopt, getopt_long, getopt_long_only, optarg, optind, opterr, optopt - Parse command-line options
#include &&
int getopt(int argc, char * const argv[],
const char *optstring);
extern char *optarg;
extern int optind, opterr, optopt;
#include &&
int getopt_long(int argc, char * const argv[],
const char *optstring,
const struct option *longopts, int *longindex);
int getopt_long_only(int argc, char * const argv[],
const char *optstring,
const struct option *longopts, int *longindex);
Feature Test Macro Requirements for glibc (see (7)):
getopt(): _POSIX_C_SOURCE &= 2 || _XOPEN_SOURCE
getopt_long(), getopt_long_only(): _GNU_SOURCE
Description
The getopt() function parses the command-line arguments. Its arguments argc and argv are the argument count and array as passed to the
main() function on program invocation. An element of argv that starts with '-' (and is not exactly "-" or "--") is an option element. The
characters of this element (aside from the initial '-') are option characters. If getopt() is called repeatedly, it returns successively each of the
option characters from each of the option elements.
The variable optind is the index of the next element to be processed in argv. The system initializes this value to 1. The caller can reset it
to 1 to restart scanning of the same argv, or when scanning a new argument vector.
If getopt() finds another option character, it returns that character, updating the external variable optind and a static variable
nextchar so that the next call to getopt() can resume the scan with the following option character or argv-element.
If there are no more option characters, getopt() returns -1. Then optind is the index in argv of the first argv-element that is
not an option.
optstring is a string containing the legitimate option characters. If such a character is followed by a colon, the option requires an argument, so
getopt() places a pointer to the following text in the same argv-element, or the text of the following argv-element, in optarg. Two
colons mean an option t if there is text in the current argv-element (i.e., in the same word as the option name itself, for
example, "-oarg"), then it is returned in optarg, otherwise optarg is set to zero. This is a GNU extension. If optstring contains W
followed by a semicolon, then -W foo is treated as the long option --foo. (The -W option is reserved by POSIX.2 for implementation
extensions.) This behavior is a GNU extension, not available with libraries before glibc 2.
By default, getopt() permutes the contents of argv as it scans, so that eventually all the nonoptions are at the end. Two other modes are also
implemented. If the first character of optstring is '+' or the environment variable POSIXLY_CORRECT is set, then option processing stops as soon
as a nonoption argument is encountered. If the first character of optstring is '-', then each nonoption argv-element is handled as if it were the
argument of an option with character code 1. (This is used by programs that were written to expect options and other argv-elements in any order and that
care about the ordering of the two.) The special argument "--" forces an end of option-scanning regardless of the scanning mode.
If getopt() does not recognize an option character, it prints an error message to stderr, stores the character in optopt, and returns
'?'. The calling program may prevent the error message by setting opterr to 0.
If getopt() finds an option character in argv that was not included in optstring, or if it detects a missing option argument, it
returns '?' and sets the external variable optopt to the actual option character. If the first character (following any optional '+' or '-' described
above) of optstring is a colon (':'), then getopt() returns ':' instead of '?' to indicate a missing option argument. If an error was detected,
and the first character of optstring is not a colon, and the external variable opterr is nonzero (which is the default), getopt() prints
an error message.
getopt_long() and getopt_long_only()
The getopt_long() function works like getopt() except that it also accepts long options, started with two dashes. (If the program accepts only
long options, then optstring should be specified as an empty string (""), not NULL.) Long option names may be abbreviated if the abbreviation is unique
or is an exact match for some defined option. A long option may take a parameter, of the form --arg=param or --arg param.
longopts is a pointer to the first element of an array of struct option declared in && as
struct option {
const char *
The meanings of the different fields are:
is the name of the long option.
is: no_argument (or 0) if the option does
required_argument (or 1) if the option
optional_argument (or 2) if the option takes an optional argument.
specifies how results are returned for a long option. If flag is NULL, then getopt_long() returns val. (For example, the calling
program may set val to the equivalent short option character.) Otherwise, getopt_long() returns 0, and flag points to a variable which is
set to val if the option is found, but left unchanged if the option is not found.
is the value to return, or to load into the variable pointed to by flag.
The last element of the array has to be filled with zeros.
If longindex is not NULL, it points to a variable which is set to the index of the long option relative to longopts.
getopt_long_only() is like getopt_long(), but '-' as well as "--" can indicate a long option. If an option that starts with '-' (not "--")
doesn't match a long option, but does match a short option, it is parsed as a short option instead.
Return Value
If an option was successfully found, then getopt() returns the option character. If all command-line options have been parsed, then getopt()
returns -1. If getopt() encounters an option character that was not in optstring, then '?' is returned. If getopt() encounters an option
with a missing argument, then the return value depends on the first character in optstring: if it is ':', then ':' otherwise '?' is
getopt_long() and getopt_long_only() also return the option character when a short option is recognized. For a long option, they return
val if flag is NULL, and 0 otherwise. Error and -1 returns are the same as for getopt(), plus '?' for an ambiguous match or an extraneous
parameter.
Environment
POSIXLY_CORRECT
If this is set, then option processing stops as soon as a nonoption argument is encountered.
_&PID&_GNU_nonoption_argv_flags_
This variable was used by (1) 2.0 to communicate to glibc which arguments are the results of wildcard expansion and so should not be considered
as options. This behavior was removed in (1) version 2.01, but the support remains in glibc.
Conforming To
POSIX.2 and POSIX.1-2001, provided the environment variable POSIXLY_CORRECT is set. Otherwise, the elements of argv aren't really const,
because we permute them. We pretend they're const in the prototype to be compatible with other systems.
The use of '+' and '-' in optstring is a GNU extension.
On some older implementations, getopt() was declared in &&. SUSv1 permitted the declaration to appear in either
&& or &&. POSIX.1-2001 marked the use of && for this purpose as LEGACY. POSIX.1-2001 does not
allow the declaration to appear in &&.
getopt_long() and getopt_long_only():
These functions are GNU extensions.
A program that scans multiple argument vectors, or rescans the same vector more than once, and wants to make use of GNU extensions such as '+' and '-' at
the start of optstring, or changes the value of POSIXLY_CORRECT between scans, must reinitialize getopt() by resetting optind to 0,
rather than the traditional value of 1. (Resetting to 0 forces the invocation of an internal initialization routine that rechecks POSIXLY_CORRECT and
checks for GNU extensions in optstring.)
The POSIX.2 specification of getopt() has a technical error described in POSIX.2 Interpretation 150. The GNU implementation (and probably all other
implementations) implements the correct behavior rather than that specified.
The following trivial example program uses getopt() to handle two program options: -n, with and -t val, which
expects an associated value.
#include &&
#include &&
#include &&
main(int argc, char *argv[])
int flags,
int nsecs,
nsecs = 0;
flags = 0;
while ((opt = getopt(argc, argv, "nt:")) != -1) {
switch (opt) {
flags = 1;
nsecs = atoi(optarg);
default: /* '?' */
fprintf(stderr, "Usage: %s [-t nsecs] [-n] name\n",
exit(EXIT_FAILURE);
printf("flags=%d; tfnd=%d; optind=%d\n", flags, tfnd, optind);
if (optind &= argc) {
fprintf(stderr, "Expected argument after options\n");
exit(EXIT_FAILURE);
printf("name argument = %s\n", argv[optind]);
/* Other code omitted */
exit(EXIT_SUCCESS);
}The following example program illustrates the use of getopt_long() with most of its features.
#include &&
/* for printf */
#include &&
/* for exit */
#include &&
main(int argc, char **argv)
int digit_optind = 0;
while (1) {
int this_option_optind = optind ? optind : 1;
int option_index = 0;
static struct option long_options[] = {
required_argument, 0,
{"append",
no_argument,
{"delete",
required_argument, 0,
{"verbose", no_argument,
{"create",
required_argument, 0, 'c'},
required_argument, 0,
c = getopt_long(argc, argv, "abc:d:012",
long_options, &option_index);
if (c == -1)
switch (c) {
printf("option %s", long_options[option_index].name);
if (optarg)
printf(" with arg %s", optarg);
printf("\n");
if (digit_optind != 0 && digit_optind != this_option_optind)
printf("digits occur in two different argv-elements.\n");
digit_optind = this_option_
printf("option %c\n", c);
printf("option a\n");
printf("option b\n");
printf("option c with value '%s'\n", optarg);
printf("option d with value '%s'\n", optarg);
printf("?? getopt returned character code 0%o ??\n", c);
if (optind & argc) {
printf("non-option ARGV-elements: ");
while (optind & argc)
printf("%s ", argv[optind++]);
printf("\n");
exit(EXIT_SUCCESS);
Referenced By
Site SearchC 语言基础测试题目---理论_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
C 语言基础测试题目---理论
上传于||暂无简介
阅读已结束,如果下载本文需要使用1下载券
想免费下载本文?
定制HR最喜欢的简历
下载文档到电脑,查找使用更方便
还剩3页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢How to Call Java Functions from C Using JNI - CodeProject
Sign in using
258.4K views6.6K downloads45 bookmarked
&4.47 (35 votes)
4.47/5 - 35 votes3 removedμ 4.26, σa 1.71 []
Rate this:
Introduction
This article describes the methodology to use Java code in C/C++. I have not only discussed simple parameter passing and returning, but complex data structures such as structures and structure arrays to Java functions as well.
Background
A few days ago, my manager asked me to write code in C/C++ that will use Java classes in other projects. It took me a lot of time to grab some information on how to call simple functions as well as pass/return complex data types. I found many articles describing C/C++ function calls in Java using JNI, but very few discussing calling Java functions in C/C++ using JNI. At that time, I decided to write an article so that other people could get help from it.
Using the code
The CTest.cpp file contains the code that calls different functions from Java classes. Java classes that are used in this project are given here under:
HelloWorld.java
ControlDetail.java
WorkOrder.java
ReturnData.java
HelloWorld.java contains the functions that will be called from CTest.cpp. The other three Java classes are simply used in place of structures in Java. As there is no structure concept in Java, we can use classes for that purpose. That is what the other three .java files contain.
HelloWorld.java contains the following functions that will be called from C/C++ code:
public static void main(String args[])
public static void TestCall(String szArg)
public static int DisplayStruct(ControlDetail ctrlDetail)
public static void DisplayStructArray(WorkOrder ArrWO[])
public static Object ReturnObjFunc()
To call these functions from C/C++, first you need to load the JVM using the following function:
JNIEnv* create_vm(JavaVM ** jvm) {
JavaVMInitArgs vm_
options.optionString = "-Djava.class.path=D:\\Java Src\\TestStruct";
vm_args.version = JNI_VERSION_1_6;
vm_args.nOptions = 1;
vm_args.options = &
vm_args.ignoreUnrecognized = 0;
int ret = JNI_CreateJavaVM(jvm, (void**)&env, &vm_args);
if(ret & 0)
printf("\nUnable to Launch JVM\n");
Kindly note that to use this code, you will have to modify the options.optionString variable. You will have to set the path of the Java code: where the Java classes are placed. Currently, it being set to D:\Java Src\TestStruct. You can modify it to you situation. You will also need to modify the JDK version information in the above code, as shown below:
vm_args.version = JNI_VERSION_1_6; //JDK version. This indicates version 1.6
Modify it if you have another JDK version installed.
To call a specific Java function from C, you need to do the following:
Obtain the class reference using the FindClass(,,) method.
Obtain the method IDs of the functions of the class that you want to call using the GetStaticMethodID and GetMethodID function calls.
Call the functions using CallStaticVoidMethod, CallStaticIntMethod, and CallStaticObjectMethod.
One important thing to be noted here is specifying the function signatures while obtaining the method IDs.
To obtain the correct method signature, you can use the following Java command:
javap -s -p HelloWorld
It will display you the signature of each function in the HelloWorld class. These signatures can be used to obtain the method IDs. The result of the above command can be seen below:
D:\Java Src\TestStruct&javap -s -p HelloWorld
Compiled from "HelloWorld.java"
public class HelloWorld extends java.lang.Object{
public HelloWorld();
Signature: ()V
public static void main(java.lang.String[]);
Signature: ([Ljava/lang/S)V
public static void TestCall(java.lang.String);
Signature: (Ljava/lang/S)V
public static int DisplayStruct(ControlNEDetail);
Signature: (LControlNED)I
public static void DisplayStructArray(WorkOrder[]);
Signature: ([LWorkO)V
public static java.lang.Object ReturnObjFunc();
Signature: ()Ljava/lang/O
Kindly note that while specifying the method name in the GetMethodID function, if the method is a constructor, then its method name will be &init&.
Prerequisites
Before traveling down a difficult path, it is important to understand the basic concepts and to have various frameworks and tools installed on your computer.
You will need the . I recommend .
Any C/C++ compiler installed.
How to run
To use this code, follow the instructions below:
Compile the *.java files using the javac command.
Compile the CTest.cpp file using any C++ I used MSVC++ 6.
Converting this code to pure C from C++
The attached code is written in C++. To convert this code into pure C, you will have to modify the following in the CTest.cpp file:
(*env)-&FunctionName(env,args,..);
instead of:
env-&FunctionName(args,..);
This article, along with any associated source code and files, is licensed under
Software Developer (Senior)
United Kingdom
Ahmad Qarshi is an IT Consultant and have good expertise in different development technologies. He loves to code in .NET, JavaFX, Delphi, XSLT/Schematron. Above all very keen to learn new stuff
Comments and Discussions
General &&
Suggestion &&
Question &&
Last Updated 13 Jan 2008
Article Copyright 2008 by ajalilqarshiEverything else
Copyright & ,}

我要回帖

更多关于 int argc char argv 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信